1
0
Fork 0

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 <mcostalba@gmail.com>
sf_2.3.1_base
Marco Costalba 2012-01-02 23:40:14 +01:00
parent d282cf6964
commit f80c50bcdd
4 changed files with 17 additions and 13 deletions

View File

@ -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;

View File

@ -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;
};

View File

@ -367,7 +367,7 @@ template Value ThreadsManager::split<true>(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();
}
}

View File

@ -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);