From 1982fe25f817c29aef9dd156869a53e520ce3629 Mon Sep 17 00:00:00 2001 From: xoto10 Date: Wed, 3 Apr 2019 08:35:55 +0100 Subject: [PATCH] Use average bestMoveChanges across all threads #2072 The current update only by main thread depends on the luck of whether main thread sees any/many changes to the best move or not. It then makes large, lumpy changes to the time to be used (1x, 2x, 3x, etc) depending on that sample of 1. Use the average across all threads to get a more reliable number with a smoother distribution. STC @ 5+0.05 th 4 : LLR: 2.95 (-2.94,2.94) [0.50,4.50] Total: 51899 W: 11446 L: 11029 D: 29424 http://tests.stockfishchess.org/tests/view/5ca32ff20ebc5925cf0016fb STC @ 5+0.05 th 8 : LLR: 2.96 (-2.94,2.94) [0.50,4.50] Total: 13851 W: 2843 L: 2620 D: 8388 http://tests.stockfishchess.org/tests/view/5ca35ae00ebc5925cf001adb LTC @ 20+0.2 th 8 : LLR: 2.95 (-2.94,2.94) [0.00,3.50] Total: 48527 W: 7941 L: 7635 D: 32951 http://tests.stockfishchess.org/tests/view/5ca37cb70ebc5925cf001cec Further work: Similar changes might be possible for the fallingEval and timeReduction calculations (and elsewhere?), using either the min, average or max values across all threads. Bench 3506898 --- src/search.cpp | 21 ++++++++++++--------- src/thread.h | 4 ++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 972482eb..30f28072 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -191,8 +191,11 @@ void MainThread::search() { else { for (Thread* th : Threads) + { + th->bestMoveChanges = 0; if (th != this) th->start_searching(); + } Thread::search(); // Let's start searching! } @@ -283,7 +286,7 @@ void Thread::search() { Move lastBestMove = MOVE_NONE; Depth lastBestMoveDepth = DEPTH_ZERO; MainThread* mainThread = (this == Threads.main() ? Threads.main() : nullptr); - double timeReduction = 1.0; + double timeReduction = 1, totBestMoveChanges = 0; Color us = rootPos.side_to_move(); std::memset(ss-7, 0, 10 * sizeof(Stack)); @@ -294,9 +297,6 @@ void Thread::search() { bestValue = delta = alpha = -VALUE_INFINITE; beta = VALUE_INFINITE; - if (mainThread) - mainThread->bestMoveChanges = 0; - size_t multiPV = Options["MultiPV"]; Skill skill(Options["Skill Level"]); @@ -328,7 +328,7 @@ void Thread::search() { { // Age out PV variability metric if (mainThread) - mainThread->bestMoveChanges *= 0.517; + totBestMoveChanges /= 2; // Save the last iteration's scores before first PV line is searched and // all the move scores except the (new) PV are set to -VALUE_INFINITE. @@ -459,7 +459,7 @@ void Thread::search() { && !Threads.stop && !mainThread->stopOnPonderhit) { - double fallingEval = (306 + 9 * (mainThread->previousScore - bestValue)) / 581.0; + double fallingEval = (314 + 9 * (mainThread->previousScore - bestValue)) / 581.0; fallingEval = clamp(fallingEval, 0.5, 1.5); // If the bestMove is stable over several iterations, reduce time accordingly @@ -467,7 +467,10 @@ void Thread::search() { double reduction = std::pow(mainThread->previousTimeReduction, 0.528) / timeReduction; // Use part of the gained time from a previous stable move for the current move - double bestMoveInstability = 1.0 + mainThread->bestMoveChanges; + for (Thread* th : Threads) + totBestMoveChanges += th->bestMoveChanges; + + double bestMoveInstability = 1 + totBestMoveChanges / Threads.size(); // Stop the search if we have only one legal move, or if available time elapsed if ( rootMoves.size() == 1 @@ -1101,8 +1104,8 @@ moves_loop: // When in check, search starts from here // We record how often the best move has been changed in each // iteration. This information is used for time management: When // the best move changes frequently, we allocate some more time. - if (moveCount > 1 && thisThread == Threads.main()) - ++static_cast(thisThread)->bestMoveChanges; + if (moveCount > 1) + ++thisThread->bestMoveChanges; } else // All other moves but the PV are set to the lowest value: this diff --git a/src/thread.h b/src/thread.h index af506609..7a27aab1 100644 --- a/src/thread.h +++ b/src/thread.h @@ -63,7 +63,7 @@ public: size_t pvIdx, pvLast; int selDepth, nmpMinPly; Color nmpColor; - std::atomic nodes, tbHits; + std::atomic nodes, tbHits, bestMoveChanges; Position rootPos; Search::RootMoves rootMoves; @@ -85,7 +85,7 @@ struct MainThread : public Thread { void search() override; void check_time(); - double bestMoveChanges, previousTimeReduction; + double previousTimeReduction; Value previousScore; int callsCnt; bool stopOnPonderhit; -- 2.39.2