dfpnParallel.cc
Go to the documentation of this file.
00001 /* dfpnParallel.cc
00002  */
00003 #include "osl/checkmate/dfpnParallel.h"
00004 #include "osl/checkmate/proofTreeDepthDfpn.h"
00005 #include <boost/ptr_container/ptr_vector.hpp>
00006 #include <boost/thread/thread.hpp>
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::numCPUs();
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, 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, 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<boost::thread> threads;
00080   for (size_t i=0; i<num_threads; ++i)
00081     threads.push_back(new boost::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<boost::thread> threads;
00134   for (size_t i=0; i<num_threads; ++i)
00135     threads.push_back(new boost::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 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 // ;;; Local Variables:
00170 // ;;; mode:c++
00171 // ;;; c-basic-offset:2
00172 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines