From: Leonid Pechenik Date: Wed, 28 Feb 2018 11:36:36 +0000 (+0100) Subject: Tweak time management X-Git-Url: https://git.sesse.net/?p=stockfish;a=commitdiff_plain;h=ad5d86c7714ae3eaad71e8b3630d38c29dd2c3fe;ds=sidebyside Tweak time management Using a SPSA tuning session to optimize the time management parameters. With SPSA tuning it is not always possible to say where improvements came from. Maybe some variables changed randomly or because result was not sensitive enough to them. So my explanation of changes will not be necessarily correct, but here it is. • When decrease of thinking time was added by Joost a few months ago if best move has not changed for several plies, one more competing indicator was introduced for the same purpose along with increase in score and absence of fail low at root. It seems that tuning put relatively more importance on that new indicator what allowed to save time. • Some of this saved time is distributed proportionally between all moves and some more time were given to moves when score dropped a lot or best move changed. • It looks also that SPSA redistributed more time from the beginning to later stages of game via other changes in variables - maybe because contempt made game to last longer or for whatever reason. All of this is just small tweaks here and there (a few percentages changes). STC (10+0.1): LLR: 2.96 (-2.94,2.94) [0.00,4.00] Total: 18970 W: 4268 L: 4029 D: 10673 http://tests.stockfishchess.org/tests/view/5a9291a40ebc590297cc8881 LTC (60+0.6): LLR: 2.95 (-2.94,2.94) [0.00,4.00] Total: 72027 W: 12263 L: 11878 D: 47886 http://tests.stockfishchess.org/tests/view/5a92d7510ebc590297cc88ef Additional non-regression tests at other time controls Sudden death 60s: LLR: 2.95 (-2.94,2.94) [-4.00,0.00] Total: 14444 W: 2715 L: 2608 D: 9121 http://tests.stockfishchess.org/tests/view/5a9445850ebc590297cc8a65 40 moves repeating at LTC: LLR: 2.95 (-2.94,2.94) [-4.00,0.00] Total: 10309 W: 1880 L: 1759 D: 6670 http://tests.stockfishchess.org/tests/view/5a9566ec0ebc590297cc8be1 This is a functional patch only for time management, but the bench does not reflect this because it uses fixed depth search, so the number of nodes does not change during bench. No functional change. --- diff --git a/src/search.cpp b/src/search.cpp index 3874852b..e9afc1c5 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -325,7 +325,7 @@ void Thread::search() { // Age out PV variability metric if (mainThread) - mainThread->bestMoveChanges *= 0.505, mainThread->failedLow = false; + mainThread->bestMoveChanges *= 0.517, mainThread->failedLow = false; // 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. @@ -444,21 +444,21 @@ void Thread::search() { const int F[] = { mainThread->failedLow, bestValue - mainThread->previousScore }; - int improvingFactor = std::max(229, std::min(715, 357 + 119 * F[0] - 6 * F[1])); + int improvingFactor = std::max(246, std::min(832, 306 + 119 * F[0] - 6 * F[1])); // If the bestMove is stable over several iterations, reduce time accordingly timeReduction = 1.0; for (int i : {3, 4, 5}) if (lastBestMoveDepth * i < completedDepth) - timeReduction *= 1.3; + timeReduction *= 1.25; // Use part of the gained time from a previous stable move for the current move double unstablePvFactor = 1.0 + mainThread->bestMoveChanges; - unstablePvFactor *= std::pow(mainThread->previousTimeReduction, 0.51) / timeReduction; + unstablePvFactor *= std::pow(mainThread->previousTimeReduction, 0.528) / timeReduction; // Stop the search if we have only one legal move, or if available time elapsed if ( rootMoves.size() == 1 - || Time.elapsed() > Time.optimum() * unstablePvFactor * improvingFactor / 605) + || Time.elapsed() > Time.optimum() * unstablePvFactor * improvingFactor / 581) { // If we are allowed to ponder do not stop the search now but // keep pondering until the GUI sends "ponderhit" or "stop". diff --git a/src/timeman.cpp b/src/timeman.cpp index 035fe335..f6ead0b2 100644 --- a/src/timeman.cpp +++ b/src/timeman.cpp @@ -33,8 +33,8 @@ namespace { enum TimeType { OptimumTime, MaxTime }; const int MoveHorizon = 50; // Plan time management at most this many moves ahead - const double MaxRatio = 7.09; // When in trouble, we can step over reserved time with this ratio - const double StealRatio = 0.35; // However we must not steal time from remaining moves over this ratio + const double MaxRatio = 7.3; // When in trouble, we can step over reserved time with this ratio + const double StealRatio = 0.34; // However we must not steal time from remaining moves over this ratio // move_importance() is a skew-logistic function based on naive statistical @@ -44,9 +44,9 @@ namespace { double move_importance(int ply) { - const double XScale = 7.64; - const double XShift = 58.4; - const double Skew = 0.183; + const double XScale = 6.85; + const double XShift = 64.5; + const double Skew = 0.171; return pow((1 + exp((ply - XShift) / XScale)), -Skew) + DBL_MIN; // Ensure non-zero } diff --git a/src/ucioption.cpp b/src/ucioption.cpp index aa2e2d8a..4d925d68 100644 --- a/src/ucioption.cpp +++ b/src/ucioption.cpp @@ -68,7 +68,7 @@ void init(OptionsMap& o) { o["Skill Level"] << Option(20, 0, 20); o["Move Overhead"] << Option(30, 0, 5000); o["Minimum Thinking Time"] << Option(20, 0, 5000); - o["Slow Mover"] << Option(89, 10, 1000); + o["Slow Mover"] << Option(84, 10, 1000); o["nodestime"] << Option(0, 0, 10000); o["UCI_Chess960"] << Option(false); o["SyzygyPath"] << Option("", on_tb_path);