diff --git a/src/search.cpp b/src/search.cpp index 3c34f185..e5c485fc 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -127,6 +127,7 @@ namespace { }; EasyMoveManager EasyMove; + bool easyPlayed, failedLow; double BestMoveChanges; Value DrawValue[COLOR_NB]; CounterMovesHistoryStats CounterMovesHistory; @@ -368,6 +369,7 @@ void Thread::search() { { easyMove = EasyMove.get(rootPos.key()); EasyMove.clear(); + easyPlayed = false; BestMoveChanges = 0; TT.new_search(); } @@ -391,7 +393,7 @@ void Thread::search() { // Age out PV variability metric if (isMainThread) - BestMoveChanges *= 0.5; + BestMoveChanges *= 0.505, 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. @@ -452,7 +454,7 @@ void Thread::search() { if (isMainThread) { - Signals.failedLowAtRoot = true; + failedLow = true; Signals.stopOnPonderhit = false; } } @@ -512,10 +514,10 @@ void Thread::search() { // of the available time has been used or we matched an easyMove // from the previous search and just did a fast verification. if ( rootMoves.size() == 1 - || Time.elapsed() > Time.available() - || ( rootMoves[0].pv[0] == easyMove + || Time.elapsed() > Time.available() * (failedLow? 641 : 315)/640 + || ( easyPlayed = ( rootMoves[0].pv[0] == easyMove && BestMoveChanges < 0.03 - && Time.elapsed() > Time.available() / 10)) + && Time.elapsed() > Time.available() / 8))) { // If we are allowed to ponder do not stop the search now but // keep pondering until the GUI sends "ponderhit" or "stop". @@ -538,7 +540,7 @@ void Thread::search() { // Clear any candidate easy move that wasn't stable for the last search // iterations; the second condition prevents consecutive fast moves. - if (EasyMove.stableCnt < 6 || Time.elapsed() < Time.available()) + if (EasyMove.stableCnt < 6 || easyPlayed) EasyMove.clear(); // If skill level is enabled, swap best PV line with the sub-optimal one @@ -859,15 +861,10 @@ moves_loop: // When in check search starts from here ss->moveCount = ++moveCount; - if (RootNode && thisThread == Threads.main()) - { - Signals.firstRootMove = (moveCount == 1); - - if (Time.elapsed() > 3000) - sync_cout << "info depth " << depth / ONE_PLY - << " currmove " << UCI::move(move, pos.is_chess960()) - << " currmovenumber " << moveCount + thisThread->PVIdx << sync_endl; - } + if (RootNode && thisThread == Threads.main() && Time.elapsed() > 3000) + sync_cout << "info depth " << depth / ONE_PLY + << " currmove " << UCI::move(move, pos.is_chess960()) + << " currmovenumber " << moveCount + thisThread->PVIdx << sync_endl; if (PvNode) (ss+1)->pv = nullptr; @@ -1486,19 +1483,9 @@ moves_loop: // When in check search starts from here if (Limits.ponder) return; - if (Limits.use_time_management()) - { - bool stillAtFirstMove = Signals.firstRootMove.load(std::memory_order_relaxed) - && !Signals.failedLowAtRoot.load(std::memory_order_relaxed) - && elapsed > Time.available() * 3 / 4; - - if (stillAtFirstMove || elapsed > Time.maximum() - 10) - Signals.stop = true; - } - else if (Limits.movetime && elapsed >= Limits.movetime) - Signals.stop = true; - - else if (Limits.nodes && Threads.nodes_searched() >= Limits.nodes) + if ( (Limits.use_time_management() && elapsed > Time.maximum() - 10) + || (Limits.movetime && elapsed >= Limits.movetime) + || (Limits.nodes && Threads.nodes_searched() >= Limits.nodes)) Signals.stop = true; } diff --git a/src/search.h b/src/search.h index d755f1c2..2a9a3737 100644 --- a/src/search.h +++ b/src/search.h @@ -93,7 +93,7 @@ struct LimitsType { /// typically in an async fashion e.g. to stop the search by the GUI. struct SignalsType { - std::atomic_bool stop, stopOnPonderhit, firstRootMove, failedLowAtRoot; + std::atomic_bool stop, stopOnPonderhit; }; typedef std::unique_ptr> StateStackPtr; diff --git a/src/thread.cpp b/src/thread.cpp index c5c8bb0d..3b6074ac 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -174,8 +174,7 @@ void ThreadPool::start_thinking(const Position& pos, const LimitsType& limits, main()->wait_for_search_finished(); - Signals.stopOnPonderhit = Signals.firstRootMove = false; - Signals.stop = Signals.failedLowAtRoot = false; + Signals.stopOnPonderhit = Signals.stop = false; main()->rootMoves.clear(); main()->rootPos = pos; diff --git a/src/timeman.cpp b/src/timeman.cpp index 3a4e157f..47f57ab3 100644 --- a/src/timeman.cpp +++ b/src/timeman.cpp @@ -32,8 +32,8 @@ namespace { enum TimeType { OptimumTime, MaxTime }; const int MoveHorizon = 50; // Plan time management at most this many moves ahead - const double MaxRatio = 7.0; // When in trouble, we can step over reserved time with this ratio - const double StealRatio = 0.33; // However we must not steal time from remaining moves over this ratio + const double MaxRatio = 6.93; // When in trouble, we can step over reserved time with this ratio + const double StealRatio = 0.36; // However we must not steal time from remaining moves over this ratio // move_importance() is a skew-logistic function based on naive statistical @@ -43,9 +43,9 @@ namespace { double move_importance(int ply) { - const double XScale = 9.3; - const double XShift = 59.8; - const double Skew = 0.172; + const double XScale = 8.27; + const double XShift = 59.; + const double Skew = 0.179; return pow((1 + exp((ply - XShift) / XScale)), -Skew) + DBL_MIN; // Ensure non-zero } @@ -129,6 +129,4 @@ void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) if (Options["Ponder"]) optimumTime += optimumTime / 4; - - optimumTime = std::min(optimumTime, maximumTime); } diff --git a/src/timeman.h b/src/timeman.h index b6eb3485..3faba00d 100644 --- a/src/timeman.h +++ b/src/timeman.h @@ -31,7 +31,7 @@ class TimeManagement { public: void init(Search::LimitsType& limits, Color us, int ply); void pv_instability(double bestMoveChanges) { unstablePvFactor = 1 + bestMoveChanges; } - int available() const { return int(optimumTime * unstablePvFactor * 0.76); } + int available() const { return int(optimumTime * unstablePvFactor * 1.016); } int maximum() const { return maximumTime; } int elapsed() const { return int(Search::Limits.npmsec ? Threads.nodes_searched() : now() - startTime); } diff --git a/src/ucioption.cpp b/src/ucioption.cpp index f493e840..23af481b 100644 --- a/src/ucioption.cpp +++ b/src/ucioption.cpp @@ -61,12 +61,12 @@ void init(OptionsMap& o) { o["Threads"] << Option(1, 1, 128, on_threads); o["Hash"] << Option(16, 1, MaxHashMB, on_hash_size); o["Clear Hash"] << Option(on_clear_hash); - o["Ponder"] << Option(true); + o["Ponder"] << Option(false); o["MultiPV"] << Option(1, 1, 500); 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(80, 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);