diff --git a/src/cluster.cpp b/src/cluster.cpp index 85c3ed56..a0a2be71 100644 --- a/src/cluster.cpp +++ b/src/cluster.cpp @@ -48,21 +48,8 @@ static MPI_Comm StopComm = MPI_COMM_NULL; static MPI_Datatype TTEntryDatatype = MPI_DATATYPE_NULL; static std::vector TTBuff; -static MPI_Op BestMoveOp = MPI_OP_NULL; static MPI_Datatype MIDatatype = MPI_DATATYPE_NULL; -static void BestMove(void* in, void* inout, int* len, MPI_Datatype* datatype) { - if (*datatype != MIDatatype) - MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); - MoveInfo* l = static_cast(in); - MoveInfo* r = static_cast(inout); - for (int i=0; i < *len; ++i) - { - if (l[i].depth >= r[i].depth && l[i].score >= r[i].score) - r[i] = l[i]; - } -} - void init() { int thread_support; constexpr std::array TTblocklens = {1, 1, 1, 1, 1, 1, 1}; @@ -80,7 +67,8 @@ void init() { MPI_INT16_T, MPI_UINT8_T, MPI_INT8_T}; - const std::array MIdisps = {offsetof(MoveInfo, depth), + const std::array MIdisps = {offsetof(MoveInfo, move), + offsetof(MoveInfo, depth), offsetof(MoveInfo, score), offsetof(MoveInfo, rank)}; @@ -101,9 +89,8 @@ void init() { &TTEntryDatatype); MPI_Type_commit(&TTEntryDatatype); - MPI_Type_create_hindexed_block(3, 1, MIdisps.data(), MPI_INT, &MIDatatype); + MPI_Type_create_hindexed_block(4, 1, MIdisps.data(), MPI_INT, &MIDatatype); MPI_Type_commit(&MIDatatype); - MPI_Op_create(BestMove, false, &BestMoveOp); MPI_Comm_dup(MPI_COMM_WORLD, &InputComm); MPI_Comm_dup(MPI_COMM_WORLD, &TTComm); @@ -236,8 +223,32 @@ void save(Thread* thread, TTEntry* tte, } } -void reduce_moves(MoveInfo& mi) { - MPI_Allreduce(MPI_IN_PLACE, &mi, 1, MIDatatype, BestMoveOp, MoveComm); +void pick_moves(MoveInfo& mi) { + MoveInfo* pMoveInfo = NULL; + if (is_root()) { + pMoveInfo = (MoveInfo*)malloc(sizeof(MoveInfo) * size()); + } + MPI_Gather(&mi, 1, MIDatatype, pMoveInfo, 1, MIDatatype, 0, MoveComm); + if (is_root()) { + std::map votes; + int minScore = pMoveInfo[0].score; + 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++) { + 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) { + bestVote = votes[pMoveInfo[i].move]; + mi = pMoveInfo[i]; + } + } + free(pMoveInfo); + } + MPI_Bcast(&mi, 1, MIDatatype, 0, MoveComm); } } diff --git a/src/cluster.h b/src/cluster.h index 4502e518..aea6a12e 100644 --- a/src/cluster.h +++ b/src/cluster.h @@ -33,6 +33,7 @@ class Thread; namespace Cluster { struct MoveInfo { + int move; int depth; int score; int rank; @@ -70,7 +71,7 @@ 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 reduce_moves(MoveInfo& mi); +void pick_moves(MoveInfo& mi); void sync_start(); void sync_stop(); @@ -89,7 +90,7 @@ inline void save(Thread* thread, TTEntry* tte, (void)thread; tte->save(k, v, b, d, m, ev); } -inline void reduce_moves(MoveInfo&) { } +inline void pick_moves(MoveInfo&) { } inline void sync_start() { } inline void sync_stop() { } diff --git a/src/search.cpp b/src/search.cpp index 805040e8..89214e22 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -288,10 +288,11 @@ void MainThread::search() { } } - Cluster::MoveInfo mi{bestThread->completedDepth, + Cluster::MoveInfo mi{bestThread->rootMoves[0].pv[0], + bestThread->completedDepth, bestThread->rootMoves[0].score, Cluster::rank()}; - Cluster::reduce_moves(mi); + Cluster::pick_moves(mi); previousScore = static_cast(mi.score);