00001
00002
00003 #include "osl/checkmate/dfpnParallel.h"
00004 #include "osl/checkmate/proofTreeDepthDfpn.h"
00005 #include <boost/ptr_container/ptr_vector.hpp>
00006 #include <thread>
00007
00008 #ifdef OSL_DFPN_SMP
00009 osl::checkmate::
00010 DfpnParallel::DfpnParallel(size_t threads)
00011 : table(0), num_threads(threads), state(0)
00012 {
00013 if (threads == 0)
00014 num_threads = OslConfig::concurrency();
00015 workers.reset(new Dfpn[num_threads]);
00016 for (size_t i=0; i<num_threads; ++i)
00017 workers[i].setParallel(i, &shared);
00018 }
00019
00020 osl::checkmate::
00021 DfpnParallel::~DfpnParallel()
00022 {
00023 #ifdef DFPN_DEBUG
00024 table->testTable();
00025 #endif
00026 }
00027
00028 void osl::checkmate::
00029 DfpnParallel::setTable(DfpnTable *new_table)
00030 {
00031 table = new_table;
00032 for (size_t i=0; i<num_threads; ++i)
00033 workers[i].setTable(table);
00034 }
00035
00036 const osl::checkmate::ProofDisproof
00037 osl::checkmate::
00038 DfpnParallel::hasCheckmateMove(const NumEffectState& state, const HashKey& key,
00039 const PathEncoding& path, size_t limit, Move& best_move,
00040 Move last_move, std::vector<Move> *pv)
00041 {
00042 PieceStand proof;
00043 return hasCheckmateMove(state, key, path, limit, best_move, proof, last_move, pv);
00044 }
00045
00046 struct osl::checkmate::DfpnParallel::AttackWorker
00047 {
00048 DfpnParallel *parent;
00049 int thread_id;
00050
00051 AttackWorker(DfpnParallel *p, int id)
00052 : parent(p), thread_id(id)
00053 {
00054 }
00055 void operator()() const
00056 {
00057 assert(! parent->shared.data[thread_id].restart);
00058 WorkerData& work = parent->worker_data[thread_id];
00059 work.result = parent->workers[thread_id].hasCheckmateMove
00060 (*(parent->state), parent->key, parent->path,
00061 parent->limit, work.best_move, work.proof, parent->last_move);
00062 parent->workers[thread_id].clear();
00063 }
00064 };
00065
00066 const osl::checkmate::ProofDisproof
00067 osl::checkmate::
00068 DfpnParallel::hasCheckmateMove(const NumEffectState& state, const HashKey& key,
00069 const PathEncoding& path, size_t limit, Move& best_move, PieceStand& proof,
00070 Move last_move, std::vector<Move> *pv)
00071 {
00072 this->state = &state;
00073 this->key = key;
00074 this->path = path;
00075 this->last_move = last_move;
00076 this->limit = limit;
00077 shared.clear();
00078 worker_data.reset(new WorkerData[num_threads]);
00079 boost::ptr_vector<std::thread> threads;
00080 for (size_t i=0; i<num_threads; ++i)
00081 threads.push_back(new std::thread(AttackWorker(this, i)));
00082 ProofDisproof ret;
00083 unsigned int min_proof = ProofDisproof::PROOF_MAX;
00084 for (size_t i=0; i<num_threads; ++i) {
00085 threads[i].join();
00086 if (ret.isFinal()
00087 || (worker_data[i].result.proof() >= min_proof
00088 && ! worker_data[i].result.isFinal()))
00089 continue;
00090 ret = worker_data[i].result;
00091 min_proof = ret.proof();
00092 best_move = worker_data[i].best_move;
00093 proof = worker_data[i].proof;
00094 }
00095 if (pv && ret.isCheckmateSuccess()) {
00096 ProofTreeDepthDfpn analyzer(*table);
00097 analyzer.retrievePV(state, true, *pv);
00098 }
00099 return ret;
00100 }
00101
00102 struct osl::checkmate::DfpnParallel::DefenseWorker
00103 {
00104 DfpnParallel *parent;
00105 int thread_id;
00106
00107 DefenseWorker(DfpnParallel *p, int id)
00108 : parent(p), thread_id(id)
00109 {
00110 }
00111 void operator()() const
00112 {
00113 WorkerData& work = parent->worker_data[thread_id];
00114 work.result = parent->workers[thread_id].hasEscapeMove
00115 (*(parent->state), parent->key, parent->path,
00116 parent->limit, parent->last_move);
00117 }
00118 };
00119
00120 const osl::checkmate::ProofDisproof
00121 osl::checkmate::
00122 DfpnParallel::hasEscapeMove(const NumEffectState& state,
00123 const HashKey& key, const PathEncoding& path,
00124 size_t limit, Move last_move)
00125 {
00126 this->state = &state;
00127 this->key = key;
00128 this->path = path;
00129 this->last_move = last_move;
00130 this->limit = limit;
00131 shared.clear();
00132 worker_data.reset(new WorkerData[num_threads]);
00133 boost::ptr_vector<std::thread> threads;
00134 for (size_t i=0; i<num_threads; ++i)
00135 threads.push_back(new std::thread(DefenseWorker(this, i)));
00136 ProofDisproof ret;
00137 unsigned int min_disproof = ProofDisproof::DISPROOF_MAX;
00138 for (size_t i=0; i<num_threads; ++i) {
00139 threads[i].join();
00140 if (worker_data[i].result.disproof() >= min_disproof)
00141 continue;
00142 ret = worker_data[i].result;
00143 min_disproof = ret.disproof();
00144 }
00145 return ret;
00146 }
00147
00148 size_t osl::checkmate::
00149 DfpnParallel::nodeCount() const
00150 {
00151 size_t sum = 0;
00152 for (size_t i=0; i<num_threads; ++i)
00153 sum += workers[i].nodeCount();
00154 return sum;
00155 }
00156
00157 #ifndef MINIMAL
00158 void osl::checkmate::
00159 DfpnParallel::analyze(const PathEncoding& path,
00160 const NumEffectState& src, const std::vector<Move>& moves) const
00161 {
00162 if (num_threads > 0)
00163 workers[0].analyze(path, src, moves);
00164 }
00165 #endif
00166 #endif
00167
00168
00169
00170
00171
00172