X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=1c000b5bad78a8d847d5f4d8c3ecfe130dff2e48;hp=d59edbaeefcbf4be8ba40ea965156a21e0bf387a;hb=36a93d90f76d32e16a5f2acb09b7de2d67225021;hpb=2c237da54647bb7526f3512bea183eb44919cdda diff --git a/src/search.cpp b/src/search.cpp index d59edbae..1c000b5b 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -39,7 +39,6 @@ namespace Search { - SignalsType Signals; LimitsType Limits; } @@ -154,7 +153,6 @@ namespace { void update_pv(Move* pv, Move move, Move* childPv); void update_cm_stats(Stack* ss, Piece pc, Square s, int bonus); void update_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, int bonus); - void check_time(); } // namespace @@ -193,7 +191,6 @@ void Search::clear() { for (Thread* th : Threads) { - th->resetCalls = true; th->counterMoves.fill(MOVE_NONE); th->history.fill(0); @@ -204,6 +201,7 @@ void Search::clear() { th->counterMoveHistory[NO_PIECE][0].fill(CounterMovePruneThreshold - 1); } + Threads.main()->callsCnt = 0; Threads.main()->previousScore = VALUE_INFINITE; } @@ -272,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) @@ -362,8 +360,8 @@ void Thread::search() { // Iterative deepening loop until requested to stop or the target depth is reached while ( (rootDepth += ONE_PLY) < DEPTH_MAX - && !Signals.stop - && (!Limits.depth || Threads.main()->rootDepth / ONE_PLY <= Limits.depth)) + && !Threads.stop + && !(Limits.depth && mainThread && rootDepth / ONE_PLY > Limits.depth)) { // Distribute search depths across the threads if (idx) @@ -383,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) @@ -411,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 @@ -432,7 +430,7 @@ void Thread::search() { if (mainThread) { mainThread->failedLow = true; - Signals.stopOnPonderhit = false; + Threads.stopOnPonderhit = false; } } else if (bestValue >= beta) @@ -454,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) @@ -472,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 @@ -499,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; } } @@ -551,7 +549,7 @@ namespace { Depth extension, newDepth; Value bestValue, value, ttValue, eval; bool ttHit, inCheck, givesCheck, singularExtensionNode, improving; - bool captureOrPromotion, doFullDepthSearch, moveCountPruning, skipQuiets; + bool captureOrPromotion, doFullDepthSearch, moveCountPruning, skipQuiets, ttCapture; Piece moved_piece; int moveCount, quietCount; @@ -564,23 +562,8 @@ namespace { ss->ply = (ss-1)->ply + 1; // Check for the available remaining time - if (thisThread->resetCalls.load(std::memory_order_relaxed)) - { - thisThread->resetCalls = false; - - // At low node count increase the checking rate to about 0.1% of nodes - // otherwise use a default value. - thisThread->callsCnt = Limits.nodes ? std::min(4096, int(Limits.nodes / 1024)) - : 4096; - } - - if (--thisThread->callsCnt <= 0) - { - for (Thread* th : Threads) - th->resetCalls = true; - - check_time(); - } + if (thisThread == Threads.main()) + static_cast(thisThread)->check_time(); // Used to send selDepth info to GUI if (PvNode && thisThread->maxPly < ss->ply) @@ -589,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()]; @@ -668,7 +651,7 @@ namespace { if (err != TB::ProbeState::FAIL) { - thisThread->tbHits++; + thisThread->tbHits.fetch_add(1, std::memory_order_relaxed); int drawScore = TB::UseRule50 ? 1 : 0; @@ -836,6 +819,7 @@ moves_loop: // When in check search starts from here && (tte->bound() & BOUND_LOWER) && tte->depth() >= depth - 3 * ONE_PLY; skipQuiets = false; + ttCapture = false; // Step 11. Loop through moves // Loop through all pseudo-legal moves until no moves remain or a beta cutoff occurs @@ -954,6 +938,9 @@ moves_loop: // When in check search starts from here continue; } + if (move == ttMove && captureOrPromotion) + ttCapture = true; + // Update the current move (this must be done after singular extension search) ss->currentMove = move; ss->history = &thisThread->counterMoveHistory[moved_piece][to_sq(move)]; @@ -973,6 +960,10 @@ moves_loop: // When in check search starts from here r -= r ? ONE_PLY : DEPTH_ZERO; else { + // Increase reduction if ttMove is a capture + if (ttCapture) + r += ONE_PLY; + // Increase reduction for cut nodes if (cutNode) r += 2 * ONE_PLY; @@ -1040,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) @@ -1101,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; */ @@ -1256,9 +1247,6 @@ moves_loop: // When in check search starts from here { assert(is_ok(move)); - // Speculative prefetch as early as possible - prefetch(TT.first_entry(pos.key_after(move))); - givesCheck = type_of(move) == NORMAL && !pos.discovered_check_candidates() ? pos.check_squares(type_of(pos.piece_on(from_sq(move)))) & to_sq(move) : pos.gives_check(move); @@ -1300,6 +1288,9 @@ moves_loop: // When in check search starts from here && !pos.see_ge(move)) continue; + // Speculative prefetch as early as possible + prefetch(TT.first_entry(pos.key_after(move))); + // Check for legality just before making the move if (!pos.legal(move)) { @@ -1467,11 +1458,19 @@ moves_loop: // When in check search starts from here return best; } +} // namespace // check_time() is used to print debug info and, more importantly, to detect // when we are out of available time and thus stop the search. - void check_time() { + void MainThread::check_time() { + + if (--callsCnt > 0) + return; + + // At low node count increase the checking rate to about 0.1% of nodes + // otherwise use a default value. + callsCnt = Limits.nodes ? std::min(4096, int(Limits.nodes / 1024)) : 4096; static TimePoint lastInfoTime = now(); @@ -1491,11 +1490,9 @@ 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; } -} // namespace - /// UCI::pv() formats PV information according to the UCI protocol. UCI requires /// that all (if any) unsearched PV lines are sent using a previous search score.