From: Joost VandeVondele Date: Thu, 13 Jul 2017 23:07:19 +0000 (-0700) Subject: Move stop signal to Threads X-Git-Url: https://git.sesse.net/?p=stockfish;a=commitdiff_plain;h=36a93d90f76d32e16a5f2acb09b7de2d67225021;hp=0371a8f8c4a043cb3e7d08b5b8e7d08d49f28324 Move stop signal to Threads Instead of having Signals in the search namespace, make the stop variables part of the Threads structure. This moves more of the shared (atomic) variables towards the thread-related structures, making their role more clear. No functional change Closes #1149 --- diff --git a/src/search.cpp b/src/search.cpp index 09e3c4fa..1c000b5b 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -39,7 +39,6 @@ namespace Search { - SignalsType Signals; LimitsType Limits; } @@ -271,18 +270,18 @@ void MainThread::search() { Time.availableNodes += Limits.inc[us] - Threads.nodes_searched(); // When we reach the maximum depth, we can arrive here without a raise of - // Signals.stop. However, if we are pondering or in an infinite search, + // Threads.stop. However, if we are pondering or in an infinite search, // the UCI protocol states that we shouldn't print the best move before the // GUI sends a "stop" or "ponderhit" command. We therefore simply wait here - // until the GUI sends one of those commands (which also raises Signals.stop). - if (!Signals.stop && (Limits.ponder || Limits.infinite)) + // until the GUI sends one of those commands (which also raises Threads.stop). + if (!Threads.stop && (Limits.ponder || Limits.infinite)) { - Signals.stopOnPonderhit = true; - wait(Signals.stop); + Threads.stopOnPonderhit = true; + wait(Threads.stop); } // Stop the threads if not already stopped - Signals.stop = true; + Threads.stop = true; // Wait until all threads have finished for (Thread* th : Threads) @@ -361,7 +360,7 @@ void Thread::search() { // Iterative deepening loop until requested to stop or the target depth is reached while ( (rootDepth += ONE_PLY) < DEPTH_MAX - && !Signals.stop + && !Threads.stop && !(Limits.depth && mainThread && rootDepth / ONE_PLY > Limits.depth)) { // Distribute search depths across the threads @@ -382,7 +381,7 @@ void Thread::search() { rm.previousScore = rm.score; // MultiPV loop. We perform a full root search for each PV line - for (PVIdx = 0; PVIdx < multiPV && !Signals.stop; ++PVIdx) + for (PVIdx = 0; PVIdx < multiPV && !Threads.stop; ++PVIdx) { // Reset aspiration window starting size if (rootDepth >= 5 * ONE_PLY) @@ -410,7 +409,7 @@ void Thread::search() { // If search has been stopped, we break immediately. Sorting and // writing PV back to TT is safe because RootMoves is still // valid, although it refers to the previous iteration. - if (Signals.stop) + if (Threads.stop) break; // When failing high/low give some update (without cluttering @@ -431,7 +430,7 @@ void Thread::search() { if (mainThread) { mainThread->failedLow = true; - Signals.stopOnPonderhit = false; + Threads.stopOnPonderhit = false; } } else if (bestValue >= beta) @@ -453,11 +452,11 @@ void Thread::search() { if (!mainThread) continue; - if (Signals.stop || PVIdx + 1 == multiPV || Time.elapsed() > 3000) + if (Threads.stop || PVIdx + 1 == multiPV || Time.elapsed() > 3000) sync_cout << UCI::pv(rootPos, rootDepth, alpha, beta) << sync_endl; } - if (!Signals.stop) + if (!Threads.stop) completedDepth = rootDepth; if (!mainThread) @@ -471,12 +470,12 @@ void Thread::search() { if ( Limits.mate && bestValue >= VALUE_MATE_IN_MAX_PLY && VALUE_MATE - bestValue <= 2 * Limits.mate) - Signals.stop = true; + Threads.stop = true; // Do we have time for the next iteration? Can we stop searching now? if (Limits.use_time_management()) { - if (!Signals.stop && !Signals.stopOnPonderhit) + if (!Threads.stop && !Threads.stopOnPonderhit) { // Stop the search if only one legal move is available, or if all // of the available time has been used, or if we matched an easyMove @@ -498,9 +497,9 @@ void Thread::search() { // If we are allowed to ponder do not stop the search now but // keep pondering until the GUI sends "ponderhit" or "stop". if (Limits.ponder) - Signals.stopOnPonderhit = true; + Threads.stopOnPonderhit = true; else - Signals.stop = true; + Threads.stop = true; } } @@ -573,7 +572,7 @@ namespace { if (!rootNode) { // Step 2. Check for aborted search and immediate draw - if (Signals.stop.load(std::memory_order_relaxed) || pos.is_draw(ss->ply) || ss->ply >= MAX_PLY) + if (Threads.stop.load(std::memory_order_relaxed) || pos.is_draw(ss->ply) || ss->ply >= MAX_PLY) return ss->ply >= MAX_PLY && !inCheck ? evaluate(pos) : DrawValue[pos.side_to_move()]; @@ -1032,7 +1031,7 @@ moves_loop: // When in check search starts from here // Finished searching the move. If a stop occurred, the return value of // the search cannot be trusted, and we return immediately without // updating best move, PV and TT. - if (Signals.stop.load(std::memory_order_relaxed)) + if (Threads.stop.load(std::memory_order_relaxed)) return VALUE_ZERO; if (rootNode) @@ -1093,7 +1092,7 @@ moves_loop: // When in check search starts from here // completed. But in this case bestValue is valid because we have fully // searched our subtree, and we can anyhow save the result in TT. /* - if (Signals.stop) + if (Threads.stop) return VALUE_DRAW; */ @@ -1491,7 +1490,7 @@ moves_loop: // When in check search starts from here if ( (Limits.use_time_management() && elapsed > Time.maximum() - 10) || (Limits.movetime && elapsed >= Limits.movetime) || (Limits.nodes && Threads.nodes_searched() >= (uint64_t)Limits.nodes)) - Signals.stop = true; + Threads.stop = true; } diff --git a/src/search.h b/src/search.h index 55a1bf6b..7c46980b 100644 --- a/src/search.h +++ b/src/search.h @@ -21,7 +21,6 @@ #ifndef SEARCH_H_INCLUDED #define SEARCH_H_INCLUDED -#include #include #include "misc.h" @@ -92,15 +91,6 @@ struct LimitsType { TimePoint startTime; }; - -/// SignalsType struct stores atomic flags updated during the search, typically -/// in an async fashion e.g. to stop the search by the GUI. - -struct SignalsType { - std::atomic_bool stop, stopOnPonderhit; -}; - -extern SignalsType Signals; extern LimitsType Limits; void init(); diff --git a/src/thread.cpp b/src/thread.cpp index b4e9f8aa..66f74b99 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -187,7 +187,7 @@ void ThreadPool::start_thinking(Position& pos, StateListPtr& states, main()->wait_for_search_finished(); - Search::Signals.stopOnPonderhit = Search::Signals.stop = false; + stopOnPonderhit = stop = false; Search::Limits = limits; Search::RootMoves rootMoves; diff --git a/src/thread.h b/src/thread.h index dc0c51c2..77517b07 100644 --- a/src/thread.h +++ b/src/thread.h @@ -101,6 +101,8 @@ struct ThreadPool : public std::vector { uint64_t nodes_searched() const; uint64_t tb_hits() const; + std::atomic_bool stop, stopOnPonderhit; + private: StateListPtr setupStates; }; diff --git a/src/uci.cpp b/src/uci.cpp index f3b5f54c..afc775c1 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -178,15 +178,15 @@ void UCI::loop(int argc, char* argv[]) { is >> skipws >> token; // The GUI sends 'ponderhit' to tell us to ponder on the same move the - // opponent has played. In case Signals.stopOnPonderhit is set we are + // opponent has played. In case Threads.stopOnPonderhit is set we are // waiting for 'ponderhit' to stop the search (for instance because we // already ran out of time), otherwise we should continue searching but // switching from pondering to normal search. if ( token == "quit" || token == "stop" - || (token == "ponderhit" && Search::Signals.stopOnPonderhit)) + || (token == "ponderhit" && Threads.stopOnPonderhit)) { - Search::Signals.stop = true; + Threads.stop = true; Threads.main()->start_searching(true); // Could be sleeping } else if (token == "ponderhit")