Go to the documentation of this file.00001
00002
00003 #ifndef _ALPHABETA2PARALLEL_H
00004 #define _ALPHABETA2PARALLEL_H
00005
00006 #ifdef OSL_SMP
00007
00008 #include "osl/search/alphaBeta2.h"
00009 #include "osl/misc/atomicCounter.h"
00010 #include "osl/stl/vector.h"
00011 #include <boost/shared_ptr.hpp>
00012 #include <boost/thread/thread.hpp>
00013 #include <boost/thread/mutex.hpp>
00014 #include <boost/thread/condition.hpp>
00015 #include <boost/ptr_container/ptr_vector.hpp>
00016
00017 #define SPLIT_STAT
00018
00019
00020 namespace osl
00021 {
00022 namespace search
00023 {
00024
00025 struct AlphaBeta2ParallelCommon : boost::noncopyable
00026 {
00027 struct TreeInfoCommon
00028 {
00029 int thread_id;
00030 volatile int nprocs;
00031 MoveLogProb best_move;
00032 AlphaBeta2Window window;
00033 int value;
00034 size_t nodes_searched;
00035 bool is_root, in_pv;
00036 Player turn;
00037 };
00038 struct TreeInfo : public TreeInfoCommon
00039 {
00040 CArray<volatile int, OslConfig::MaxThreads> siblings;
00041 volatile int parent;
00042 MoveLogProbVector moves;
00043 volatile int move_index, search_value;
00044 int alpha_update, last_alpha_update;
00045 volatile bool used;
00046 LightMutex lock;
00047
00048 TreeInfo() : used(0)
00049 {
00050 siblings.fill(0);
00051 }
00052 void set(const TreeInfo& parent, int max_threads)
00053 {
00054 TreeInfoCommon::operator=(parent);
00055 used = true;
00056 for (int i=0; i<max_threads; i++)
00057 siblings[i] = 0;
00058 search_value = 0;
00059 }
00060 };
00061 struct LivingThreadLock;
00062 typedef SearchState2::checkmate_t checkmate_t;
00063 static const int MaxBlocksPerCpu = 16;
00064 static const int MaxBlocks = OslConfig::MaxThreads*MaxBlocksPerCpu+1;
00065 CArray<volatile int, OslConfig::MaxThreads> job;
00066 CArray<checkmate_t*, OslConfig::MaxThreads> checkmate;
00067
00068 CArray<TreeInfo,MaxBlocks> info;
00070 CArray<volatile int,OslConfig::MaxThreads> waiting;
00071 CArray<boost::thread*,OslConfig::MaxThreads> threads;
00072 boost::mutex lock_smp;
00073 boost::condition condition_smp;
00074 volatile int smp_idle;
00075 volatile bool quit;
00076 unsigned int parallel_splits;
00077 unsigned int max_split_depth, descendant_reject, descendant_test;
00078
00079 boost::mutex living_threads_lock;
00080 boost::condition living_threads_condition;
00081 volatile int living_threads;
00082
00083 int max_threads, max_thread_group;
00084 int split_min_limit;
00085
00086 int my_id;
00087 AtomicCounter parallel_abort;
00088 AtomicCounter cancelled_splits;
00089 bool started;
00090
00091 AlphaBeta2ParallelCommon();
00092 ~AlphaBeta2ParallelCommon();
00093 static checkmate_t*& checkmateSearcher(SearchState2& state) { return state.checkmate_searcher; }
00094
00095 void waitAll();
00096 bool isDescendant(int elder, int younger);
00097
00098 struct SplitFailed {};
00099 };
00100 template <class EvalT>
00101 struct AlphaBeta2Parallel : public AlphaBeta2ParallelCommon
00102 {
00103 struct Worker
00104 {
00105 AlphaBeta2Parallel *shared;
00106 int thread_id;
00107 Worker(int tid, AlphaBeta2Parallel *shared);
00108 void operator()();
00109 };
00110
00111 typedef AlphaBeta2Tree<EvalT> tree_t;
00112 CArray<tree_t*,MaxBlocks> tree;
00113 tree_t *master;
00114
00115 explicit AlphaBeta2Parallel(tree_t *master);
00116 ~AlphaBeta2Parallel();
00117 void threadStart();
00118
00119 void testStop();
00120
00121 void search(int tree_id);
00122 void threadWait(int thread_id, int waiting);
00124 bool split(tree_t *tree, int tree_id, int thread_id, int max_split);
00125 void stopThread(int tree_id);
00126 void copyToParent(int parent, int child);
00128 int copyToChild(int parent, int thread_id);
00129
00130 int treeId(tree_t *tree);
00131 int parentID(int tree_id) { return info[tree_id].parent; }
00132 TreeInfo* parent(int tree_id) { return &info[parentID(tree_id)]; }
00133 const std::pair<MoveLogProb,size_t> nextMove(int tree_id);
00134 size_t checkmateCount() const;
00135 size_t mainCheckmateCount() const;
00136 };
00137 }
00138 }
00139
00140 #endif
00141
00142 #endif
00143
00144
00145
00146