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/ptr_container/ptr_vector.hpp>
00015
00016 #define SPLIT_STAT
00017
00018
00019 namespace osl
00020 {
00021 namespace search
00022 {
00023
00024 struct AlphaBeta2Parallel : boost::noncopyable
00025 {
00026 struct TreeInfoCommon
00027 {
00028 int thread_id;
00029 volatile int nprocs;
00030 MoveLogProb best_move;
00031 AlphaBeta2::Window window;
00032 int value;
00033 size_t nodes_searched;
00034 bool is_root, in_pv;
00035 Player turn;
00036 };
00037 struct TreeInfo : public TreeInfoCommon
00038 {
00039 CArray<volatile int, OslConfig::MaxThreads> siblings;
00040 volatile int parent;
00041 MoveLogProbVector moves;
00042 volatile int move_index, search_value;
00043 int alpha_update, last_alpha_update;
00044 volatile bool used;
00045 LightMutex lock;
00046
00047 TreeInfo() : used(0)
00048 {
00049 siblings.fill(0);
00050 }
00051 void set(const TreeInfo& parent, int max_threads)
00052 {
00053 TreeInfoCommon::operator=(parent);
00054 used = true;
00055 for (int i=0; i<max_threads; i++)
00056 siblings[i] = 0;
00057 search_value = 0;
00058 }
00059 };
00060 struct Worker
00061 {
00062 AlphaBeta2Parallel *shared;
00063 int thread_id;
00064 Worker(int tid, AlphaBeta2Parallel *shared);
00065 void operator()();
00066 };
00067 struct LivingThreadLock;
00068
00069 typedef SearchState2::checkmate_t checkmate_t;
00070 static const int MaxBlocksPerCpu = 32;
00071 static const int MaxBlocks = OslConfig::MaxThreads*MaxBlocksPerCpu+1;
00072 CArray<volatile int, OslConfig::MaxThreads> job;
00073 CArray<checkmate_t*, OslConfig::MaxThreads> checkmate;
00074 CArray<AlphaBeta2Tree*,MaxBlocks> tree;
00075 CArray<TreeInfo,MaxBlocks> info;
00077 CArray<volatile int,OslConfig::MaxThreads> waiting;
00078 CArray<boost::thread*,OslConfig::MaxThreads> threads;
00079 boost::mutex lock_smp, lock_io;
00080 boost::condition condition_smp;
00081 volatile int smp_idle;
00082 volatile bool quit;
00083 volatile int stop_by_alarm;
00084 unsigned int parallel_splits;
00085 unsigned int max_split_depth, descendant_reject, descendant_test;
00086
00087 boost::mutex living_threads_lock;
00088 boost::condition living_threads_condition;
00089 int living_threads;
00090
00091 int max_threads, max_thread_group;
00092 int split_min_limit;
00093 AlphaBeta2Tree *master;
00094 int my_id;
00095 AtomicCounter parallel_abort;
00096 AtomicCounter cancelled_splits;
00097 bool started;
00098
00099 explicit AlphaBeta2Parallel(AlphaBeta2Tree *master);
00100 ~AlphaBeta2Parallel();
00101 void threadStart();
00102
00103 void testStop();
00104 void waitAll();
00105
00106 void search(int tree_id);
00107 void threadWait(int thread_id, int waiting);
00109 bool split(AlphaBeta2Tree *tree, int tree_id, int thread_id);
00110 void stopThread(int tree_id);
00111 void copyToParent(int parent, int child);
00113 int copyToChild(int parent, int thread_id);
00114
00115 int treeId(AlphaBeta2Tree *tree);
00116 int parentID(int tree_id) { return info[tree_id].parent; }
00117 TreeInfo* parent(int tree_id) { return &info[parentID(tree_id)]; }
00118 const std::pair<MoveLogProb,size_t> nextMove(int tree_id);
00119 size_t checkmateCount() const;
00120 size_t mainCheckmateCount() const;
00121
00122 bool isDescendant(int elder, int younger);
00123 };
00124 struct SplitFailed {};
00125 }
00126 }
00127
00128 #endif
00129
00130 #endif
00131
00132
00133
00134