X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=58feb77d7038fc49dcb24821dbf9b762fa84925c;hp=35565d87841b083bb8527aac4c01520e98942bc3;hb=cbcc581a86417ead9f75ae3a9556f97df63b22bf;hpb=d004ec924de058f46076b23c0cf244d46e752ac7 diff --git a/src/search.cpp b/src/search.cpp index 35565d87..58feb77d 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -38,6 +38,7 @@ #include "lock.h" #include "san.h" #include "search.h" +#include "timeman.h" #include "thread.h" #include "tt.h" #include "ucioption.h" @@ -198,7 +199,7 @@ namespace { Depth PassedPawnExtension[2], PawnEndgameExtension[2], MateThreatExtension[2]; // Minimum depth for use of singular extension - const Depth SingularExtensionDepth[2] = { 8 * OnePly /* non-PV */, 6 * OnePly /* PV */}; + const Depth SingularExtensionDepth[2] = { 7 * OnePly /* non-PV */, 6 * OnePly /* PV */}; // If the TT move is at least SingularExtensionMargin better then the // remaining ones we will extend it. @@ -250,8 +251,8 @@ namespace { int MultiPV; // Time managment variables - int SearchStartTime, MaxNodes, MaxDepth, MaxSearchTime; - int AbsoluteMaxSearchTime, ExtraSearchTime, ExactMaxTime; + int SearchStartTime, MaxNodes, MaxDepth, OptimumSearchTime; + int MaximumSearchTime, ExtraSearchTime, ExactMaxTime; bool UseTimeManagement, InfiniteSearch, PonderSearch, StopOnPonderhit; bool FirstRootMove, AbortSearch, Quit, AspirationFailLow; @@ -360,20 +361,6 @@ void init_search() { } -// SearchStack::init() initializes a search stack entry. -// Called at the beginning of search() when starting to examine a new node. -void SearchStack::init() { - - currentMove = bestMove = MOVE_NONE; -} - -// SearchStack::initKillers() initializes killers for a search stack entry -void SearchStack::initKillers() { - - killers[0] = killers[1] = mateKiller = MOVE_NONE; -} - - /// perft() is our utility to verify move generation is bug free. All the legal /// moves up to given depth are generated and counted and the sum returned. @@ -414,7 +401,7 @@ bool think(const Position& pos, bool infinite, bool ponder, int time[], int incr // Initialize global search variables StopOnPonderhit = AbortSearch = Quit = AspirationFailLow = false; - MaxSearchTime = AbsoluteMaxSearchTime = ExtraSearchTime = 0; + OptimumSearchTime = MaximumSearchTime = ExtraSearchTime = 0; NodesSincePoll = 0; TM.resetNodeCounters(); SearchStartTime = get_system_time(); @@ -487,37 +474,13 @@ bool think(const Position& pos, bool infinite, bool ponder, int time[], int incr int myIncrement = increment[pos.side_to_move()]; if (UseTimeManagement) { - if (!movesToGo) // Sudden death time control - { - if (myIncrement) - { - MaxSearchTime = myTime / 30 + myIncrement; - AbsoluteMaxSearchTime = Max(myTime / 4, myIncrement - 100); - } - else // Blitz game without increment - { - MaxSearchTime = myTime / 30; - AbsoluteMaxSearchTime = myTime / 8; - } - } - else // (x moves) / (y minutes) - { - if (movesToGo == 1) - { - MaxSearchTime = myTime / 2; - AbsoluteMaxSearchTime = (myTime > 3000)? (myTime - 500) : ((myTime * 3) / 4); - } - else - { - MaxSearchTime = myTime / Min(movesToGo, 20); - AbsoluteMaxSearchTime = Min((4 * myTime) / movesToGo, myTime / 3); - } - } + get_search_times(myTime, myIncrement, movesToGo, pos.startpos_ply_counter(), + &OptimumSearchTime, &MaximumSearchTime); if (get_option_value_bool("Ponder")) { - MaxSearchTime += MaxSearchTime / 4; - MaxSearchTime = Min(MaxSearchTime, AbsoluteMaxSearchTime); + OptimumSearchTime += OptimumSearchTime / 4; + OptimumSearchTime = Min(OptimumSearchTime, MaximumSearchTime); } } @@ -663,20 +626,20 @@ namespace { if ( Iteration >= 8 && EasyMove == pv[0] && ( ( rml.get_move_cumulative_nodes(0) > (nodes * 85) / 100 - && current_search_time() > MaxSearchTime / 16) + && current_search_time() > OptimumSearchTime / 16) ||( rml.get_move_cumulative_nodes(0) > (nodes * 98) / 100 - && current_search_time() > MaxSearchTime / 32))) + && current_search_time() > OptimumSearchTime / 32))) stopSearch = true; // Add some extra time if the best move has changed during the last two iterations if (Iteration > 5 && Iteration <= 50) - ExtraSearchTime = BestMoveChangesByIteration[Iteration] * (MaxSearchTime / 2) - + BestMoveChangesByIteration[Iteration-1] * (MaxSearchTime / 3); + ExtraSearchTime = BestMoveChangesByIteration[Iteration] * (OptimumSearchTime / 2) + + BestMoveChangesByIteration[Iteration-1] * (OptimumSearchTime / 3); // Stop search if most of MaxSearchTime is consumed at the end of the // iteration. We probably don't have enough time to search the first // move at the next iteration anyway. - if (current_search_time() > ((MaxSearchTime + ExtraSearchTime) * 80) / 128) + if (current_search_time() > ((OptimumSearchTime + ExtraSearchTime) * 80) / 128) stopSearch = true; if (stopSearch) @@ -763,7 +726,7 @@ namespace { isCheck = pos.is_check(); // Step 1. Initialize node (polling is omitted at root) - ss->init(); + ss->currentMove = ss->bestMove = MOVE_NONE; // Step 2. Check for aborted search (omitted at root) // Step 3. Mate distance pruning (omitted at root) @@ -1016,9 +979,9 @@ namespace { Move movesSearched[256]; EvalInfo ei; StateInfo st; - const TTEntry* tte; + const TTEntry *tte, *ttx; Key posKey; - Move ttMove, move, excludedMove; + Move ttMove, move, excludedMove, threatMove; Depth ext, newDepth; Value bestValue, value, oldAlpha; Value refinedValue, nullValue, futilityValueScaled; // Non-PV specific @@ -1026,14 +989,13 @@ namespace { bool mateThreat = false; int moveCount = 0; int threadID = pos.thread(); - Move threatMove = MOVE_NONE; refinedValue = bestValue = value = -VALUE_INFINITE; oldAlpha = alpha; // Step 1. Initialize node and poll. Polling can abort search TM.incrementNodeCounter(threadID); - ss->init(); - (ss+2)->initKillers(); + ss->currentMove = ss->bestMove = threatMove = MOVE_NONE; + (ss+2)->killers[0] = (ss+2)->killers[1] = (ss+2)->mateKiller = MOVE_NONE; if (threadID == 0 && ++NodesSincePoll > NodesBetweenPolls) { @@ -1077,7 +1039,7 @@ namespace { // Refresh tte entry to avoid aging TT.store(posKey, tte->value(), tte->type(), tte->depth(), ttMove, tte->static_value(), tte->king_danger()); - ss->currentMove = ttMove; // Can be MOVE_NONE + ss->bestMove = ttMove; // Can be MOVE_NONE return value_from_tt(tte->value(), ply); } @@ -1191,7 +1153,7 @@ namespace { if (nullValue == value_mated_in(ply + 2)) mateThreat = true; - threatMove = (ss+1)->currentMove; + threatMove = (ss+1)->bestMove; if ( depth < ThreatDepth && (ss-1)->reduction && connected_moves(pos, (ss-1)->currentMove, threatMove)) @@ -1253,9 +1215,22 @@ namespace { && move == tte->move() && ext < OnePly) { + // Avoid to do an expensive singular extension search on nodes where + // such search have already been done in the past, so assume the last + // singular extension search result is still valid. + if ( !PvNode + && depth < SingularExtensionDepth[PvNode] + 5 * OnePly + && ((ttx = TT.retrieve(pos.get_exclusion_key())) != NULL)) + { + if (is_upper_bound(ttx->type())) + ext = OnePly; + + singularExtensionNode = false; + } + Value ttValue = value_from_tt(tte->value(), ply); - if (abs(ttValue) < VALUE_KNOWN_WIN) + if (singularExtensionNode && abs(ttValue) < VALUE_KNOWN_WIN) { Value b = ttValue - SingularExtensionMargin; ss->excludedMove = move; @@ -1464,7 +1439,7 @@ namespace { if (!PvNode && tte && ok_to_use_TT(tte, depth, beta, ply)) { - ss->currentMove = ttMove; // Can be MOVE_NONE + ss->bestMove = ttMove; // Can be MOVE_NONE return value_from_tt(tte->value(), ply); } @@ -2169,9 +2144,9 @@ namespace { bool stillAtFirstMove = FirstRootMove && !AspirationFailLow - && t > MaxSearchTime + ExtraSearchTime; + && t > OptimumSearchTime + ExtraSearchTime; - bool noMoreTime = t > AbsoluteMaxSearchTime + bool noMoreTime = t > MaximumSearchTime || stillAtFirstMove; if ( (Iteration >= 3 && UseTimeManagement && noMoreTime) @@ -2192,9 +2167,9 @@ namespace { bool stillAtFirstMove = FirstRootMove && !AspirationFailLow - && t > MaxSearchTime + ExtraSearchTime; + && t > OptimumSearchTime + ExtraSearchTime; - bool noMoreTime = t > AbsoluteMaxSearchTime + bool noMoreTime = t > MaximumSearchTime || stillAtFirstMove; if (Iteration >= 3 && UseTimeManagement && (noMoreTime || StopOnPonderhit)) @@ -2214,7 +2189,7 @@ namespace { ss->reduction = Depth(0); if (i < 3) - ss->initKillers(); + ss->killers[0] = ss->killers[1] = ss->mateKiller = MOVE_NONE; } } @@ -2485,8 +2460,8 @@ namespace { #endif // Initialize global locks - lock_init(&MPLock, NULL); - lock_init(&WaitLock, NULL); + lock_init(&MPLock); + lock_init(&WaitLock); #if !defined(_MSC_VER) pthread_cond_init(&WaitCond, NULL); @@ -2498,7 +2473,7 @@ namespace { // Initialize splitPoints[] locks for (i = 0; i < MAX_THREADS; i++) for (int j = 0; j < MAX_ACTIVE_SPLIT_POINTS; j++) - lock_init(&(threads[i].splitPoints[j].lock), NULL); + lock_init(&(threads[i].splitPoints[j].lock)); // Will be set just before program exits to properly end the threads AllThreadsShouldExit = false; @@ -2792,7 +2767,7 @@ namespace { // Initialize search stack init_ss_array(ss, PLY_MAX_PLUS_2); - ss[0].init(); + ss[0].currentMove = ss[0].bestMove = MOVE_NONE; ss[0].eval = VALUE_NONE; // Generate all legal moves