From d71adc5bd979fd42ff9bbb3d2257e188aac86be9 Mon Sep 17 00:00:00 2001 From: Leonid Pechenik Date: Tue, 6 Feb 2018 05:14:55 -0500 Subject: [PATCH] Retire "Extra thinking before accepting draw PVs" MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This patch simplifies the time management code, removing the extra thinking time for moves with draw PV and increasing thinking time for all moves proportionally by around 4%. Last time when the time management was carefully tuned was 1.5-2 years ago. As new patches were getting added, time management was drifting out of optimum. This happens because when search becomes more precise pv and score are becoming more stable, there are less fail lows, best move is picked earlier and there are less best move changes. All this factors are entering in time management, and average time per move is decreasing with more and more good patches. For individual patches such effect is small (except some) and may be up or down, but when there are many of them, effect is more substantial. The same way benchmark with more and more patches is slowly drifting down on average. So my understanding that back in October adding more think time for draw PV showed positive Elo because time management was not well tuned, there was more time available, and think_hard patch applied this additional time to moves with draw PV, while just retuning back to optimum would recover Elo anyway. It is possible that absence of contempt also helped, as SF9 is showing less 0.0 scores than the October version. Anyway, to me it seems that proper place to deal with draw PV is search, and contempt sounds as much better solution. In time management there is little additional elo, and if some code is not helping like removed here, it is better to discard it. It is simpler to find genuine improvement if code is clean. • Passed STC: LLR: 2.95 (-2.94,2.94) [-3.00,1.00] Total: 20487 W: 4558 L: 4434 D: 11495 http://tests.stockfishchess.org/tests/view/5a7706ec0ebc5902971a9854 • Passed LTC: LLR: 2.96 (-2.94,2.94) [-3.00,1.00] Total: 41960 W: 7145 L: 7058 D: 27757 http://tests.stockfishchess.org/tests/view/5a778c830ebc5902971a9895 • Passed an additional non-regression [-5..0] test at the time control of 60sec for the game (sudden death) with disabled draw adjudication: LLR: 2.95 (-2.94,2.94) [-5.00,0.00] Total: 8438 W: 1675 L: 1586 D: 5177 http://tests.stockfishchess.org/tests/view/5a7c3d8d0ebc5902971a9ac0 • Passed an additional non-regression [-5..0] test at the time control of 1sec+1sec per move with disabled draw adjudication: LLR: 2.97 (-2.94,2.94) [-5.00,0.00] Total: 27664 W: 5575 L: 5574 D: 16515 http://tests.stockfishchess.org/tests/view/5a7c3e820ebc5902971a9ac3 This is a functional change for the time management code. Bench: 4983414 --- src/search.cpp | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index b9ce9a62..f422ae21 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -107,7 +107,6 @@ namespace { void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus); void update_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, int bonus); void update_capture_stats(const Position& pos, Move move, Move* captures, int captureCnt, int bonus); - bool pv_is_draw(Position& pos); // perft() is our utility to verify move generation. All the leaf nodes up // to the given depth are generated and counted, and the sum is returned. @@ -435,24 +434,19 @@ void Thread::search() { bestValue - mainThread->previousScore }; int improvingFactor = std::max(229, std::min(715, 357 + 119 * F[0] - 6 * F[1])); - Color us = rootPos.side_to_move(); - bool thinkHard = bestValue == VALUE_DRAW - && Limits.time[us] - Time.elapsed() > Limits.time[~us] - && ::pv_is_draw(rootPos); - - double unstablePvFactor = 1 + mainThread->bestMoveChanges + thinkHard; + double unstablePvFactor = 1 + mainThread->bestMoveChanges; // if the bestMove is stable over several iterations, reduce time for this move, // the longer the move has been stable, the more. // Use part of the gained time from a previous stable move for the current move. timeReduction = 1; for (int i : {3, 4, 5}) - if (lastBestMoveDepth * i < completedDepth && !thinkHard) + if (lastBestMoveDepth * i < completedDepth ) timeReduction *= 1.3; unstablePvFactor *= std::pow(mainThread->previousTimeReduction, 0.51) / timeReduction; if ( rootMoves.size() == 1 - || Time.elapsed() > Time.optimum() * unstablePvFactor * improvingFactor / 628) + || Time.elapsed() > Time.optimum() * unstablePvFactor * improvingFactor / 605) { // If we are allowed to ponder do not stop the search now but // keep pondering until the GUI sends "ponderhit" or "stop". @@ -1430,25 +1424,6 @@ moves_loop: // When in check search starts from here } } - - // Is the PV leading to a draw position? Assumes all pv moves are legal - bool pv_is_draw(Position& pos) { - - StateInfo st[MAX_PLY]; - auto& pv = pos.this_thread()->rootMoves[0].pv; - - for (size_t i = 0; i < pv.size(); ++i) - pos.do_move(pv[i], st[i]); - - bool isDraw = pos.is_draw(pv.size()); - - for (size_t i = pv.size(); i > 0; --i) - pos.undo_move(pv[i-1]); - - return isDraw; - } - - // When playing with strength handicap, choose best move among a set of RootMoves // using a statistical rule dependent on 'level'. Idea by Heinz van Saanen. -- 2.39.2