mirror of
https://github.com/official-stockfish/Stockfish.git
synced 2026-07-22 12:47:08 +00:00
multiPV: protect mated-ins and allow thread selection
This PR is a replacement for #6652 and takes into account the changes made to this part of the code since then. In multiPV analysis master may suppress genuine proven mated-in scores, if the iteration for a secondary PV line is aborted. In very rare cases, it may also evict a proven mated-in score from the best PV line with a score from an incomplete iteration of a secondary PV line. This PR avoids both. In addition, we allow best thread selection in multithreaded multiPV searches. This was originally disabled in #524. Single PV searches are not affected by this patch at all. Fixes #6642. closes https://github.com/official-stockfish/Stockfish/pull/6728 No functional change.
This commit is contained in:
committed by
Joost VandeVondele
parent
e17725f445
commit
50e8ff1e23
+20
-2
@@ -235,7 +235,7 @@ void Search::Worker::start_searching() {
|
||||
Skill skill =
|
||||
Skill(options["Skill Level"], options["UCI_LimitStrength"] ? int(options["UCI_Elo"]) : 0);
|
||||
|
||||
if (int(options["MultiPV"]) == 1 && !limits.depth && !skill.enabled())
|
||||
if (!limits.depth && !skill.enabled())
|
||||
bestThread = threads.get_best_thread()->worker.get();
|
||||
|
||||
main_manager()->bestPreviousScore = bestThread->rootMoves[0].score;
|
||||
@@ -426,6 +426,24 @@ bool Search::Worker::iterative_deepening() {
|
||||
assert(alpha >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
|
||||
}
|
||||
|
||||
// In multiPV analysis we do not let aborted searches spoil mated-in/
|
||||
// TB loss scores from a completed search in an earlier PV line.
|
||||
// A mated-in/TB loss from an aborted search for pvIdx > 0 can only become
|
||||
// bestmove in the sorting below, if the current bestmove (and hence also
|
||||
// the previously searched pvIdx - 1 line) is already a proven loss.
|
||||
if (threads.stop && pvIdx && is_loss(rootMoves[pvIdx - 1].score)
|
||||
&& rootMoves[pvIdx] < rootMoves[pvIdx - 1])
|
||||
{
|
||||
rootMoves[pvIdx].score = rootMoves[pvIdx].uciScore =
|
||||
(rootMoves[pvIdx].previousScore != -VALUE_INFINITE
|
||||
&& rootMoves[pvIdx].previousScore < rootMoves[pvIdx - 1].score)
|
||||
? rootMoves[pvIdx].previousScore
|
||||
: rootMoves[pvIdx - 1].score;
|
||||
rootMoves[pvIdx].previousScore = -VALUE_INFINITE;
|
||||
rootMoves[pvIdx].scoreLowerbound = rootMoves[pvIdx].scoreUpperbound = false;
|
||||
rootMoves[pvIdx].pv.resize(1);
|
||||
}
|
||||
|
||||
// Sort the PV lines searched so far and update the GUI
|
||||
std::stable_sort(rootMoves.begin() + pvFirst, rootMoves.begin() + pvIdx + 1);
|
||||
|
||||
@@ -452,7 +470,7 @@ bool Search::Worker::iterative_deepening() {
|
||||
// A mated-in/TB-loss score from an aborted search cannot be trusted: the loss
|
||||
// could be delayed or refuted upon exploring the remaining root-moves.
|
||||
// Thus here we roll back to the score from the previous iteration.
|
||||
else if (rootMoves[0].score != -VALUE_INFINITE && is_loss(rootMoves[0].score))
|
||||
else if (!pvIdx && rootMoves[0].score != -VALUE_INFINITE && is_loss(rootMoves[0].score))
|
||||
{
|
||||
// Bring the last best move to the front for best thread selection.
|
||||
if (!lastIterationPV.empty())
|
||||
|
||||
Reference in New Issue
Block a user