mirror of
https://github.com/official-stockfish/Stockfish.git
synced 2026-07-22 20:57:10 +00:00
prevent unproven mated-in scores in game play
This PR removes the variable threads.abortedSearch introduced in #4990 and relies on threads.stop and completedDepth instead. The logic in master is only guaranteed to work in single threaded search. For multiple threads, as soon as threads.stop is set, some of the threads may abort their search, and so their mated-in scores are not reliable. Compared to master, this patch prevents unproven mated-in scores in these multi-threaded scenarios: in game play (when time management is used) when the uci commands quit or stop are received when maximum depth is reached for go mate commands The patch will change the bestmove in those very rare situations where the bug occurs in master. This is because bestmove is taken from rootMoves[0].pv[0], which will now no longer contain unproven mated-in PVs. In that sense the patch is "functional". But of course, it does not change bench. While at it, we also fix a bug in master that suppressed PV output for inexact mated-in scores on receiving threads.stop. In cases where uciScore < score with score not being a proven loss, and where the new bestmove was different from the last completed iteration, this led to a bestmove output that did not match the final PV (which was for an exact score). Fixes #6293. Fixes #6626. closes https://github.com/official-stockfish/Stockfish/pull/6636 No functional change
This commit is contained in:
committed by
Joost VandeVondele
parent
a6d055d7e2
commit
46ac9a7e6a
+10
-8
@@ -423,12 +423,14 @@ void Search::Worker::iterative_deepening() {
|
||||
|
||||
if (mainThread
|
||||
&& (threads.stop || pvIdx + 1 == multiPV || nodes > 10000000)
|
||||
// A thread that aborted search can have mated-in/TB-loss PV and
|
||||
// score that cannot be trusted, i.e. it can be delayed or refuted
|
||||
// if we would have had time to fully search other root-moves. Thus
|
||||
// we suppress this output and below pick a proven score/PV for this
|
||||
// thread (from the previous iteration).
|
||||
&& !(threads.abortedSearch && is_loss(rootMoves[0].uciScore)))
|
||||
// A thread that aborted search can have a mated-in/TB-loss score and
|
||||
// PV that cannot be trusted, i.e. it can be delayed or refuted if we
|
||||
// would have had time to fully search other root-moves. Thus here we
|
||||
// suppress any exact mated-in/TB loss output and, if we do, below pick
|
||||
// the score/PV from the previously completed iteration with the most
|
||||
// recent bestmove change.
|
||||
&& !(threads.stop && is_loss(rootMoves[0].uciScore)
|
||||
&& rootMoves[0].score == rootMoves[0].uciScore))
|
||||
main_manager()->pv(*this, threads, tt, rootDepth);
|
||||
|
||||
if (threads.stop)
|
||||
@@ -440,7 +442,7 @@ void Search::Worker::iterative_deepening() {
|
||||
|
||||
// We make sure not to pick an unproven mated-in score,
|
||||
// in case this thread prematurely stopped search (aborted-search).
|
||||
if (threads.abortedSearch && rootMoves[0].score != -VALUE_INFINITE
|
||||
if (completedDepth != rootDepth && rootMoves[0].score != -VALUE_INFINITE
|
||||
&& is_loss(rootMoves[0].score))
|
||||
{
|
||||
// Bring the last best move to the front for best thread selection.
|
||||
@@ -1963,7 +1965,7 @@ void SearchManager::check_time(Search::Worker& worker) {
|
||||
&& ((worker.limits.use_time_management() && (elapsed > tm.maximum() || stopOnPonderhit))
|
||||
|| (worker.limits.movetime && elapsed >= worker.limits.movetime)
|
||||
|| (worker.limits.nodes && worker.threads.nodes_searched() >= worker.limits.nodes)))
|
||||
worker.threads.stop = worker.threads.abortedSearch = true;
|
||||
worker.threads.stop = true;
|
||||
}
|
||||
|
||||
// Used to correct and extend PVs for moves that have a TB (but not a mate) score.
|
||||
|
||||
+2
-2
@@ -290,8 +290,8 @@ void ThreadPool::start_thinking(const OptionsMap& options,
|
||||
|
||||
main_thread()->wait_for_search_finished();
|
||||
|
||||
main_manager()->stopOnPonderhit = stop = abortedSearch = false;
|
||||
main_manager()->ponder = limits.ponderMode;
|
||||
main_manager()->stopOnPonderhit = stop = false;
|
||||
main_manager()->ponder = limits.ponderMode;
|
||||
|
||||
increaseDepth = true;
|
||||
|
||||
|
||||
+1
-1
@@ -153,7 +153,7 @@ class ThreadPool {
|
||||
|
||||
void ensure_network_replicated();
|
||||
|
||||
std::atomic_bool stop, abortedSearch, increaseDepth;
|
||||
std::atomic_bool stop, increaseDepth;
|
||||
|
||||
auto cbegin() const noexcept { return threads.cbegin(); }
|
||||
auto begin() noexcept { return threads.begin(); }
|
||||
|
||||
Reference in New Issue
Block a user