diff --git a/src/Makefile b/src/Makefile index 49bf50f7..74fbc051 100644 --- a/src/Makefile +++ b/src/Makefile @@ -357,15 +357,11 @@ ifeq ($(OS), Android) endif ### 3.10 MPI -ifeq ($(CXX),$(filter $(CXX),mpicxx mpic++ mpiCC mpicxx.mpich)) +ifneq (,$(findstring mpi, $(CXX))) mpi = yes -endif - -ifeq ($(mpi),yes) CXXFLAGS += -DUSE_MPI -Wno-cast-qual endif - ### ========================================================================== ### Section 4. Public targets ### ========================================================================== diff --git a/src/cluster.cpp b/src/cluster.cpp index ff492b27..e0d3afc9 100644 --- a/src/cluster.cpp +++ b/src/cluster.cpp @@ -50,6 +50,7 @@ static std::vector TTBuff; static MPI_Datatype MIDatatype = MPI_DATATYPE_NULL; void init() { + int thread_support; MPI_Init_thread(nullptr, nullptr, MPI_THREAD_MULTIPLE, &thread_support); if (thread_support < MPI_THREAD_MULTIPLE) @@ -78,10 +79,12 @@ void init() { } void finalize() { + MPI_Finalize(); } bool getline(std::istream& input, std::string& str) { + int size; std::vector vec; bool state; @@ -98,27 +101,31 @@ bool getline(std::istream& input, std::string& str) { MPI_Ibcast(&size, 1, MPI_INT, 0, InputComm, &reqInput); if (is_root()) MPI_Wait(&reqInput, MPI_STATUS_IGNORE); - else { - while (true) { + else + { + while (true) + { int flag; MPI_Test(&reqInput, &flag, MPI_STATUS_IGNORE); if (flag) break; - else { + else std::this_thread::sleep_for(std::chrono::milliseconds(10)); - } } } + if (!is_root()) vec.resize(size); MPI_Bcast(vec.data(), size, MPI_CHAR, 0, InputComm); if (!is_root()) str.assign(vec.begin(), vec.end()); MPI_Bcast(&state, 1, MPI_CXX_BOOL, 0, InputComm); + return state; } void sync_start() { + stop_signal = false; // Start listening to stop signal @@ -127,15 +134,19 @@ void sync_start() { } void sync_stop() { - if (is_root()) { - if (!stop_signal && Threads.stop) { + + if (is_root()) + { + if (!stop_signal && Threads.stop) + { // Signal the cluster about stopping stop_signal = true; MPI_Ibarrier(StopComm, &reqStop); MPI_Wait(&reqStop, MPI_STATUS_IGNORE); } } - else { + else + { int flagStop; // Check if we've received any stop signal MPI_Test(&reqStop, &flagStop, MPI_STATUS_IGNORE); @@ -145,10 +156,12 @@ void sync_stop() { } int size() { + return world_size; } int rank() { + return world_rank; } @@ -185,6 +198,7 @@ void save(Thread* thread, TTEntry* tte, { if (irank == size_t(rank())) continue; + for (size_t i = irank * TTSendBufferSize ; i < (irank + 1) * TTSendBufferSize; ++i) { auto&& e = TTBuff[i]; @@ -198,7 +212,8 @@ void save(Thread* thread, TTEntry* tte, send_buff = {}; // Build up new send buffer: best 16 found across all threads - for (auto&& th : Threads) { + for (auto&& th : Threads) + { std::lock_guard lk(th->ttBuffer.mutex); for (auto&& e : th->ttBuffer.buffer) send_buff.replace(e); @@ -216,24 +231,32 @@ void save(Thread* thread, TTEntry* tte, } void pick_moves(MoveInfo& mi) { + MoveInfo* pMoveInfo = NULL; - if (is_root()) { + if (is_root()) + { pMoveInfo = (MoveInfo*)malloc(sizeof(MoveInfo) * size()); } MPI_Gather(&mi, 1, MIDatatype, pMoveInfo, 1, MIDatatype, 0, MoveComm); - if (is_root()) { + + if (is_root()) + { std::map votes; int minScore = pMoveInfo[0].score; - for (int i = 0; i < size(); i++) { + for (int i = 0; i < size(); ++i) + { minScore = std::min(minScore, pMoveInfo[i].score); votes[pMoveInfo[i].move] = 0; } - for (int i = 0; i < size(); i++) { + for (int i = 0; i < size(); ++i) + { votes[pMoveInfo[i].move] += pMoveInfo[i].score - minScore + pMoveInfo[i].depth; } int bestVote = votes[pMoveInfo[0].move]; - for (int i = 0; i < size(); i++) { - if (votes[pMoveInfo[i].move] > bestVote) { + for (int i = 0; i < size(); ++i) + { + if (votes[pMoveInfo[i].move] > bestVote) + { bestVote = votes[pMoveInfo[i].move]; mi = pMoveInfo[i]; } diff --git a/src/cluster.h b/src/cluster.h index aea6a12e..3bbe9b9c 100644 --- a/src/cluster.h +++ b/src/cluster.h @@ -44,6 +44,7 @@ using KeyedTTEntry = std::pair; constexpr std::size_t TTSendBufferSize = 16; template class TTSendBuffer : public std::array { + struct Compare { inline bool operator()(const KeyedTTEntry& lhs, const KeyedTTEntry& rhs) { return lhs.second.depth() > rhs.second.depth(); @@ -53,7 +54,9 @@ template class TTSendBuffer : public std::array public: bool replace(const KeyedTTEntry& value) { - if (compare(value, this->front())) { + + if (compare(value, this->front())) + { std::pop_heap(this->begin(), this->end(), compare); this->back() = value; std::push_heap(this->begin(), this->end(), compare); @@ -69,8 +72,7 @@ bool getline(std::istream& input, std::string& str); int size(); int rank(); inline bool is_root() { return rank() == 0; } -void save(Thread* thread, TTEntry* tte, - Key k, Value v, Bound b, Depth d, Move m, Value ev); +void save(Thread* thread, TTEntry* tte, Key k, Value v, Bound b, Depth d, Move m, Value ev); void pick_moves(MoveInfo& mi); void sync_start(); void sync_stop(); @@ -80,13 +82,14 @@ void sync_stop(); inline void init() { } inline void finalize() { } inline bool getline(std::istream& input, std::string& str) { + return static_cast(std::getline(input, str)); } constexpr int size() { return 1; } constexpr int rank() { return 0; } constexpr bool is_root() { return true; } -inline void save(Thread* thread, TTEntry* tte, - Key k, Value v, Bound b, Depth d, Move m, Value ev) { +inline void save(Thread* thread, TTEntry* tte, Key k, Value v, Bound b, Depth d, Move m, Value ev) { + (void)thread; tte->save(k, v, b, d, m, ev); } diff --git a/src/search.cpp b/src/search.cpp index 89214e22..0956180b 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -296,6 +296,7 @@ void MainThread::search() { previousScore = static_cast(mi.score); + // TODO output should be done on the cluster_root if (mi.rank == Cluster::rank()) { // Send again PV info if we have a new best thread if (!Cluster::is_root() || bestThread != this) diff --git a/src/uci.cpp b/src/uci.cpp index 00b3d10d..a62edce7 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -141,6 +141,8 @@ namespace { // a list of UCI commands is setup according to bench parameters, then // it is run one by one printing a summary at the end. + // TODO make (output?) cluster compatible + void bench(Position& pos, istream& args, StateListPtr& states) { string token;