From f80c50bcddfd02c1b93dcde067d6a7362dda53a2 Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Mon, 2 Jan 2012 23:40:14 +0100 Subject: [PATCH] Try hard not to lose on time We try hard not to lose on time even under extreme time pressure. We achieve this through 3 different but coordinated steps: 1) Increase max frequency of timer events 2) Quickly return after a stop signal 3) Take in account timer resolution With these SF played under LittleBlitzer at 1"+0.02 and 3"+0 without losing on time even one game. No functional change. Signed-off-by: Marco Costalba --- src/search.cpp | 22 +++++++++++++--------- src/search.h | 2 +- src/thread.cpp | 4 ++-- src/ucioption.cpp | 2 +- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 5e22ec4e..9d29d279 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -139,6 +139,9 @@ namespace { // better than the second best move. const Value EasyMoveMargin = Value(0x150); + // This is the minimum interval in msec between two check_time() calls + const int TimerResolution = 5; + /// Namespace variables @@ -343,8 +346,8 @@ void Search::think() { // Set best timer interval to avoid lagging under time pressure. Timer is // used to check for remaining available thinking time. - if (TimeMgr.available_time()) - Threads.set_timer(std::min(100, std::max(TimeMgr.available_time() / 8, 20))); + if (Limits.use_time_management()) + Threads.set_timer(std::min(100, std::max(TimeMgr.available_time() / 16, TimerResolution))); else Threads.set_timer(100); @@ -513,7 +516,7 @@ namespace { bestMoveNeverChanged = false; // Do we have time for the next iteration? Can we stop searching now? - if (!Signals.stop && !Signals.stopOnPonderhit && Limits.useTimeManagement()) + if (!Signals.stop && !Signals.stopOnPonderhit && Limits.use_time_management()) { bool stop = false; // Local variable, not the volatile Signals.stop @@ -865,7 +868,8 @@ split_point_start: // At split points actual search starts from here // Loop through all pseudo-legal moves until no moves remain or a beta cutoff occurs while ( bestValue < beta && (move = mp.next_move()) != MOVE_NONE - && !thread.cutoff_occurred()) + && !thread.cutoff_occurred() + && !Signals.stop) { assert(is_ok(move)); @@ -1957,11 +1961,11 @@ void Thread::idle_loop(SplitPoint* sp) { } -/// do_timer_event() is called by the timer thread when the timer triggers. It -/// is used to print debug info and, more important, to detect when we are out of +/// check_time() is called by the timer thread when the timer triggers. It is +/// used to print debug info and, more important, to detect when we are out of /// available time and so stop the search. -void do_timer_event() { +void check_time() { static int lastInfoTime; int e = elapsed_time(); @@ -1979,10 +1983,10 @@ void do_timer_event() { && !Signals.failedLowAtRoot && e > TimeMgr.available_time(); - bool noMoreTime = e > TimeMgr.maximum_time() + bool noMoreTime = e > TimeMgr.maximum_time() - TimerResolution || stillAtFirstMove; - if ( (Limits.useTimeManagement() && noMoreTime) + if ( (Limits.use_time_management() && noMoreTime) || (Limits.maxTime && e >= Limits.maxTime) /* missing nodes limit */ ) // FIXME Signals.stop = true; diff --git a/src/search.h b/src/search.h index c1b370d6..8290b41a 100644 --- a/src/search.h +++ b/src/search.h @@ -55,7 +55,7 @@ struct Stack { struct LimitsType { LimitsType() { memset(this, 0, sizeof(LimitsType)); } - bool useTimeManagement() const { return !(maxTime | maxDepth | maxNodes | infinite); } + bool use_time_management() const { return !(maxTime | maxDepth | maxNodes | infinite); } int time, increment, movesToGo, maxTime, maxDepth, maxNodes, infinite, ponder; }; diff --git a/src/thread.cpp b/src/thread.cpp index 83264801..cb0ab5e9 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -367,7 +367,7 @@ template Value ThreadsManager::split(Position&, Stack*, Value, Value, Valu // Thread::timer_loop() is where the timer thread waits maxPly milliseconds and // then calls do_timer_event(). If maxPly is 0 thread sleeps until is woken up. -extern void do_timer_event(); +extern void check_time(); void Thread::timer_loop() { @@ -376,7 +376,7 @@ void Thread::timer_loop() { lock_grab(&sleepLock); timed_wait(&sleepCond, &sleepLock, maxPly ? maxPly : INT_MAX); lock_release(&sleepLock); - do_timer_event(); + check_time(); } } diff --git a/src/ucioption.cpp b/src/ucioption.cpp index 132760c9..8162bc42 100644 --- a/src/ucioption.cpp +++ b/src/ucioption.cpp @@ -68,7 +68,7 @@ OptionsMap::OptionsMap() { o["OwnBook"] = UCIOption(true); o["MultiPV"] = UCIOption(1, 1, 500); o["Skill Level"] = UCIOption(20, 0, 20); - o["Emergency Move Horizon"] = UCIOption(40, 0, 50); + o["Emergency Move Horizon"] = UCIOption(30, 0, 50); o["Emergency Base Time"] = UCIOption(200, 0, 30000); o["Emergency Move Time"] = UCIOption(70, 0, 5000); o["Minimum Thinking Time"] = UCIOption(20, 0, 5000); -- 2.39.2