X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=22a954ae8eaa2efd757d4df91552aa20693b3a2b;hp=fbe6b2c052fa3fee50e7f98bcf37639134e438a1;hb=bfd8704a7d477a3a4d3ded55e263e7fcea2715aa;hpb=b8e6f83cfb913fa079edd3690a8720f09eb7b388 diff --git a/src/search.cpp b/src/search.cpp index fbe6b2c0..22a954ae 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -94,7 +94,7 @@ namespace { void id_loop(Position& pos); Value value_to_tt(Value v, int ply); Value value_from_tt(Value v, int ply); - void update_stats(Position& pos, Stack* ss, Move move, Depth depth, Move* quiets, int quietsCnt); + void update_stats(const Position& pos, Stack* ss, Move move, Depth depth, Move* quiets, int quietsCnt); string uci_pv(const Position& pos, int depth, Value alpha, Value beta); struct Skill { @@ -885,7 +885,7 @@ moves_loop: // When in check and at SpNode search starts from here value = -search(pos, ss+1, -(alpha+1), -alpha, d, true); - // Research at intermediate depth if reduction is very high + // Re-search at intermediate depth if reduction is very high if (value > alpha && ss->reduction >= 4 * ONE_PLY) { Depth d2 = std::max(newDepth - 2 * ONE_PLY, ONE_PLY); @@ -984,8 +984,10 @@ moves_loop: // When in check and at SpNode search starts from here // Step 19. Check for splitting the search if ( !SpNode + && Threads.size() >= 2 && depth >= Threads.minimumSplitDepth - && Threads.available_slave(thisThread) + && ( !thisThread->activeSplitPoint + || !thisThread->activeSplitPoint->allSlavesSearching) && thisThread->splitPointsSize < MAX_SPLITPOINTS_PER_THREAD) { assert(bestValue > -VALUE_INFINITE && bestValue < beta); @@ -1265,7 +1267,7 @@ moves_loop: // When in check and at SpNode search starts from here // update_stats() updates killers, history, countermoves and followupmoves stats after a fail-high // of a quiet move. - void update_stats(Position& pos, Stack* ss, Move move, Depth depth, Move* quiets, int quietsCnt) { + void update_stats(const Position& pos, Stack* ss, Move move, Depth depth, Move* quiets, int quietsCnt) { if (ss->killers[0] != move) { @@ -1530,6 +1532,7 @@ void Thread::idle_loop() { searching = false; activePosition = NULL; sp->slavesMask.reset(idx); + sp->allSlavesSearching = false; sp->nodes += pos.nodes_searched(); // Wake up the master thread so to allow it to return from the idle @@ -1544,9 +1547,39 @@ void Thread::idle_loop() { // After releasing the lock we can't access any SplitPoint related data // in a safe way because it could have been released under our feet by - // the sp master. Also accessing other Thread objects is unsafe because - // if we are exiting there is a chance that they are already freed. + // the sp master. sp->mutex.unlock(); + + // Try to late join to another split point if none of its slaves has + // already finished. + if (Threads.size() > 2) + for (size_t i = 0; i < Threads.size(); ++i) + { + int size = Threads[i]->splitPointsSize; // Local copy + sp = size ? &Threads[i]->splitPoints[size - 1] : NULL; + + if ( sp + && sp->allSlavesSearching + && available_to(Threads[i])) + { + // Recheck the conditions under lock protection + Threads.mutex.lock(); + sp->mutex.lock(); + + if ( sp->allSlavesSearching + && available_to(Threads[i])) + { + sp->slavesMask.set(idx); + activeSplitPoint = sp; + searching = true; + } + + sp->mutex.unlock(); + Threads.mutex.unlock(); + + break; // Just a single attempt + } + } } // If this thread is the master of a split point and all slaves have finished