X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=22a954ae8eaa2efd757d4df91552aa20693b3a2b;hp=60d1a86866d74b4cd3753cdc3df80ff78c525fd5;hb=bfd8704a7d477a3a4d3ded55e263e7fcea2715aa;hpb=f6e98a924af233a5e69f3494168cf5d80168c705 diff --git a/src/search.cpp b/src/search.cpp index 60d1a868..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); @@ -987,7 +987,7 @@ moves_loop: // When in check and at SpNode search starts from here && Threads.size() >= 2 && depth >= Threads.minimumSplitDepth && ( !thisThread->activeSplitPoint - || !thisThread->activeSplitPoint->allowLatejoin) + || !thisThread->activeSplitPoint->allSlavesSearching) && thisThread->splitPointsSize < MAX_SPLITPOINTS_PER_THREAD) { assert(bestValue > -VALUE_INFINITE && bestValue < beta); @@ -1267,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) { @@ -1529,9 +1529,10 @@ void Thread::idle_loop() { assert(searching); + searching = false; activePosition = NULL; sp->slavesMask.reset(idx); - sp->allowLatejoin = false; + sp->allSlavesSearching = false; sp->nodes += pos.nodes_searched(); // Wake up the master thread so to allow it to return from the idle @@ -1546,13 +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 splitpoint - if (Threads.size() <= 2 || !attempt_to_latejoin()) // FIXME: attempt_to_latejoin() is theoretically unsafe when were are exiting the program... - searching = false; + // 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 @@ -1568,44 +1595,6 @@ void Thread::idle_loop() { } } -bool Thread::attempt_to_latejoin() -{ - SplitPoint *sp; - size_t i; - bool success = false; - - for (i = 0; i < Threads.size(); ++i) - { - int size = Threads[i]->splitPointsSize; // Make a local copy to prevent size from changing under our feet. - - sp = size ? &Threads[i]->splitPoints[size - 1] : NULL; - - if ( sp - && sp->allowLatejoin - && available_to(Threads[i], true)) - break; - } - - if (i == Threads.size()) - return false; // No suitable splitpoint found! - - // Recheck conditions under lock protection - Threads.mutex.lock(); - sp->mutex.lock(); - - if ( sp->allowLatejoin - && available_to(Threads[i], true)) - { - activeSplitPoint = sp; - sp->slavesMask.set(this->idx); - success = true; - } - - sp->mutex.unlock(); - Threads.mutex.unlock(); - - return success; -} /// check_time() is called by the timer thread when the timer triggers. It is /// used to print debug info and, more importantly, to detect when we are out of