X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=c0a982363403ccae483d2fc5a00796e2323a06f6;hp=5ef8bc7fbdd9571962138d8c751af038c9aec0ac;hb=d34bb889b185e6796bbebb9bb3c2b85c8132d7cb;hpb=cca34e234cc98ed4b61e75a25f8cd0d917c2a3fa diff --git a/src/search.cpp b/src/search.cpp index 5ef8bc7f..c0a98236 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -55,9 +56,6 @@ namespace { // Set to true to force running with one thread. Used for debugging const bool FakeSplit = false; - // This is the minimum interval in msec between two check_time() calls - const int TimerResolution = 5; - // Different node types, used as template parameter enum NodeType { Root, PV, NonPV, SplitPointRoot, SplitPointPV, SplitPointNonPV }; @@ -84,7 +82,7 @@ namespace { size_t PVSize, PVIdx; TimeManager TimeMgr; - float BestMoveChanges; + double BestMoveChanges; Value DrawValue[COLOR_NB]; HistoryStats History; GainsStats Gains; @@ -131,7 +129,7 @@ void Search::init() { int mc; // moveCount // Init reductions array - for (hd = 1; hd < 64; hd++) for (mc = 1; mc < 64; mc++) + for (hd = 1; hd < 64; ++hd) for (mc = 1; mc < 64; ++mc) { double pvRed = log(double(hd)) * log(double(mc)) / 3.0; double nonPVRed = 0.33 + log(double(hd)) * log(double(mc)) / 2.25; @@ -143,17 +141,20 @@ void Search::init() { if (Reductions[0][0][hd][mc] > 2 * ONE_PLY) Reductions[0][0][hd][mc] += ONE_PLY; + + else if (Reductions[0][0][hd][mc] > 1 * ONE_PLY) + Reductions[0][0][hd][mc] += ONE_PLY / 2; } // Init futility margins array - for (d = 1; d < 16; d++) for (mc = 0; mc < 64; mc++) - FutilityMargins[d][mc] = Value(112 * int(log(double(d * d) / 2) / log(2.0) + 1.001) - 8 * mc + 45); + for (d = 1; d < 16; ++d) for (mc = 0; mc < 64; ++mc) + FutilityMargins[d][mc] = Value(112 * int(2.9 * log(double(d))) - 8 * mc + 45); // Init futility move count array - for (d = 0; d < 32; d++) + for (d = 0; d < 32; ++d) { - FutilityMoveCounts[0][d] = int(3 + 0.3 * pow(double(d ), 1.8)) * 3/4 + (2 < d && d < 5); - FutilityMoveCounts[1][d] = int(3 + 0.3 * pow(double(d + 0.98), 1.8)); + FutilityMoveCounts[0][d] = int(2.4 + 0.222 * pow(d + 0.0, 1.8)); + FutilityMoveCounts[1][d] = int(3.0 + 0.3 * pow(d + 0.98, 1.8)); } } @@ -240,19 +241,12 @@ void Search::think() { Threads[i]->maxPly = 0; Threads.sleepWhileIdle = Options["Idle Threads Sleep"]; - - // Set best timer interval to avoid lagging under time pressure. Timer is - // used to check for remaining available thinking time. - Threads.timer->msec = - Limits.use_time_management() ? std::min(100, std::max(TimeMgr.available_time() / 16, TimerResolution)) : - Limits.nodes ? 2 * TimerResolution - : 100; - + Threads.timer->run = true; Threads.timer->notify_one(); // Wake up the recurring timer id_loop(RootPos); // Let's start searching ! - Threads.timer->msec = 0; // Stop the timer + Threads.timer->run = false; // Stop the timer Threads.sleepWhileIdle = true; // Send idle threads to sleep if (Options["Write Search Log"]) @@ -333,7 +327,7 @@ namespace { while (++depth <= MAX_PLY && !Signals.stop && (!Limits.depth || depth <= Limits.depth)) { // Age out PV variability metric - BestMoveChanges *= 0.8f; + BestMoveChanges *= 0.8; // Save last iteration's scores before first PV line is searched and all // the move scores but the (new) PV are set to -VALUE_INFINITE. @@ -341,7 +335,7 @@ namespace { RootMoves[i].prevScore = RootMoves[i].score; // MultiPV loop. We perform a full root search for each PV line - for (PVIdx = 0; PVIdx < PVSize; PVIdx++) + for (PVIdx = 0; PVIdx < PVSize; ++PVIdx) { // Reset aspiration window starting size if (depth >= 5) @@ -447,6 +441,7 @@ namespace { // Stop search early if one move seems to be much better than others if ( depth >= 12 + && BestMoveChanges <= DBL_EPSILON && !stop && PVSize == 1 && bestValue > VALUE_MATED_IN_MAX_PLY @@ -810,7 +805,7 @@ moves_loop: // When in check and at SpNode search starts from here splitPoint->mutex.unlock(); } else - moveCount++; + ++moveCount; if (RootNode) { @@ -919,7 +914,7 @@ moves_loop: // When in check and at SpNode search starts from here // Check for legality only before to do the move if (!RootNode && !SpNode && !pos.legal(move, ci.pinned)) { - moveCount--; + --moveCount; continue; } @@ -1017,7 +1012,7 @@ moves_loop: // When in check and at SpNode search starts from here // iteration. This information is used for time management: When // the best move changes frequently, we allocate some more time. if (!pvMove) - BestMoveChanges++; + ++BestMoveChanges; } else // All other moves but the PV are set to the lowest value, this @@ -1188,6 +1183,11 @@ moves_loop: // When in check and at SpNode search starts from here if ( (ss->staticEval = bestValue = tte->eval_value()) == VALUE_NONE ||(ss->evalMargin = tte->eval_margin()) == VALUE_NONE) ss->staticEval = bestValue = evaluate(pos, ss->evalMargin); + + // Can ttValue be used as a better position evaluation? + if (ttValue != VALUE_NONE) + if (tte->bound() & (ttValue > bestValue ? BOUND_LOWER : BOUND_UPPER)) + bestValue = ttValue; } else ss->staticEval = bestValue = evaluate(pos, ss->evalMargin); @@ -1205,7 +1205,7 @@ moves_loop: // When in check and at SpNode search starts from here if (PvNode && bestValue > alpha) alpha = bestValue; - futilityBase = ss->staticEval + ss->evalMargin + Value(128); + futilityBase = bestValue + ss->evalMargin + Value(128); } // Initialize a MovePicker object for the current position, and prepare @@ -1443,7 +1443,7 @@ moves_loop: // When in check and at SpNode search starts from here static RKISS rk; // PRNG sequence should be not deterministic - for (int i = Time::now() % 50; i > 0; i--) + for (int i = Time::now() % 50; i > 0; --i) rk.rand(); // RootMoves are already sorted by score in descending order @@ -1514,7 +1514,7 @@ moves_loop: // When in check and at SpNode search starts from here << " multipv " << i + 1 << " pv"; - for (size_t j = 0; RootMoves[i].pv[j] != MOVE_NONE; j++) + for (size_t j = 0; RootMoves[i].pv[j] != MOVE_NONE; ++j) s << " " << move_to_uci(RootMoves[i].pv[j], pos.is_chess960()); } @@ -1730,7 +1730,7 @@ void check_time() { // Loop across all split points and sum accumulated SplitPoint nodes plus // all the currently active positions nodes. for (size_t i = 0; i < Threads.size(); ++i) - for (int j = 0; j < Threads[i]->splitPointsSize; j++) + for (int j = 0; j < Threads[i]->splitPointsSize; ++j) { SplitPoint& sp = Threads[i]->splitPoints[j]; @@ -1756,7 +1756,7 @@ void check_time() { && !Signals.failedLowAtRoot && elapsed > TimeMgr.available_time(); - bool noMoreTime = elapsed > TimeMgr.maximum_time() - 2 * TimerResolution + bool noMoreTime = elapsed > TimeMgr.maximum_time() - 2 * TimerThread::Resolution || stillAtFirstMove; if ( (Limits.use_time_management() && noMoreTime)