X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=b3418b257351f6bbe051a913427c6357598b1e95;hp=b269962f9558f006899b5aca06d8973b1153e1c6;hb=0f50f10327bc1a53d656d5d8c918a9ee413e5e84;hpb=fc234662364386800ec728643d7d6da610a560aa diff --git a/src/search.cpp b/src/search.cpp index b269962f..b3418b25 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -94,11 +94,10 @@ namespace { Thread threads[MAX_THREADS]; SplitPoint SplitPointStack[MAX_THREADS][ACTIVE_SPLIT_POINTS_MAX]; - Lock MPLock; + Lock MPLock, WaitLock; #if !defined(_MSC_VER) pthread_cond_t WaitCond; - pthread_mutex_t WaitLock; #else HANDLE SitIdleEvent[MAX_THREADS]; #endif @@ -162,7 +161,10 @@ namespace { // Step 6. Razoring + // Maximum depth for razoring const Depth RazorDepth = 4 * OnePly; + + // Dynamic razoring margin based on depth inline Value razor_margin(Depth d) { return Value(0x200 + 0x10 * d); } // Step 8. Null move search with verification search @@ -171,8 +173,12 @@ namespace { // evaluation of the position is more than NullMoveMargin below beta. const Value NullMoveMargin = Value(0x200); + // Maximum depth for use of dynamic threat detection when null move fails low + const Depth ThreatDepth = 5 * OnePly; + // Step 9. Internal iterative deepening + // Minimum depth for use of internal iterative deepening const Depth IIDDepthAtPVNodes = 5 * OnePly; const Depth IIDDepthAtNonPVNodes = 8 * OnePly; @@ -188,6 +194,7 @@ namespace { Depth CheckExtension[2], SingleEvasionExtension[2], PawnPushTo7thExtension[2]; Depth PassedPawnExtension[2], PawnEndgameExtension[2], MateThreatExtension[2]; + // Minimum depth for use of singular extension const Depth SingularExtensionDepthAtPVNodes = 6 * OnePly; const Depth SingularExtensionDepthAtNonPVNodes = 8 * OnePly; @@ -195,36 +202,35 @@ namespace { // remaining ones we will extend it. const Value SingularExtensionMargin = Value(0x20); + // Step 12. Futility pruning + // Futility margin for quiescence search + const Value FutilityMarginQS = Value(0x80); - // Search depth at iteration 1 - const Depth InitialDepth = OnePly; + // Futility lookup tables (initialized at startup) and their getter functions + int32_t FutilityMarginsMatrix[14][64]; // [depth][moveNumber] + int FutilityMoveCountArray[32]; // [depth] - // Easy move margin. An easy move candidate must be at least this much - // better than the second best move. - const Value EasyMoveMargin = Value(0x200); + inline Value futility_margin(Depth d, int mn) { return Value(d < 7*OnePly ? FutilityMarginsMatrix[Max(d, 0)][Min(mn, 63)] : 2 * VALUE_INFINITE); } + inline int futility_move_count(Depth d) { return d < 16*OnePly ? FutilityMoveCountArray[d] : 512; } - /// Lookup tables initialized at startup + // Step 14. Reduced search - // Reduction lookup tables and their getter functions + // Reduction lookup tables (initialized at startup) and their getter functions int8_t PVReductionMatrix[64][64]; // [depth][moveNumber] int8_t NonPVReductionMatrix[64][64]; // [depth][moveNumber] inline Depth pv_reduction(Depth d, int mn) { return (Depth) PVReductionMatrix[Min(d / 2, 63)][Min(mn, 63)]; } inline Depth nonpv_reduction(Depth d, int mn) { return (Depth) NonPVReductionMatrix[Min(d / 2, 63)][Min(mn, 63)]; } - // Futility lookup tables and their getter functions - const Value FutilityMarginQS = Value(0x80); - int32_t FutilityMarginsMatrix[14][64]; // [depth][moveNumber] - int FutilityMoveCountArray[32]; // [depth] + // Step. Common adjustments - inline Value futility_margin(Depth d, int mn) { return Value(d < 7*OnePly ? FutilityMarginsMatrix[Max(d, 0)][Min(mn, 63)] : 2 * VALUE_INFINITE); } - inline int futility_move_count(Depth d) { return d < 16*OnePly ? FutilityMoveCountArray[d] : 512; } - - /// Variables initialized by UCI options + // Search depth at iteration 1 + const Depth InitialDepth = OnePly; - // Depth limit for use of dynamic threat detection - Depth ThreatDepth; + // Easy move margin. An easy move candidate must be at least this much + // better than the second best move. + const Value EasyMoveMargin = Value(0x200); // Last seconds noise filtering (LSN) const bool UseLSNFiltering = true; @@ -232,6 +238,9 @@ namespace { const Value LSNValue = value_from_centipawns(200); bool loseOnTime = false; + + /// Global variables + // Iteration counters int Iteration; @@ -426,8 +435,6 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move, MateThreatExtension[1] = Depth(get_option_value_int("Mate Threat Extension (PV nodes)")); MateThreatExtension[0] = Depth(get_option_value_int("Mate Threat Extension (non-PV nodes)")); - ThreatDepth = get_option_value_int("Threat Depth") * OnePly; - Chess960 = get_option_value_bool("UCI_Chess960"); ShowCurrentLine = get_option_value_bool("UCI_ShowCurrLine"); UseLogFile = get_option_value_bool("Use Search Log"); @@ -1432,7 +1439,7 @@ namespace { // Loop through all legal moves until no moves remain or a beta cutoff occurs // Initialize a MovePicker object for the current position - MovePicker mp = MovePicker(pos, ttMove, depth, H, &ss[ply]); + MovePicker mp = MovePicker(pos, ttMove, depth, H, &ss[ply], beta); CheckInfo ci(pos); while ( bestValue < beta @@ -1492,7 +1499,7 @@ namespace { continue; // Value based pruning - Depth predictedDepth = newDepth - nonpv_reduction(depth, moveCount); //FIXME: We are ignoring condition: depth >= 3*OnePly, BUG?? + Depth predictedDepth = newDepth - nonpv_reduction(depth, moveCount); // We illogically ignore reduction condition depth >= 3*OnePly futilityValueScaled = ss[ply].eval + futility_margin(predictedDepth, moveCount) + H.gain(pos.piece_on(move_from(move)), move_to(move)) + 45; @@ -2585,7 +2592,7 @@ namespace { DWORD WINAPI init_thread(LPVOID threadID) { TM.idle_loop(*(int*)threadID, NULL); - return NULL; + return 0; } #endif @@ -2657,10 +2664,10 @@ namespace { threads[threadID].state = THREAD_SLEEPING; #if !defined(_MSC_VER) - pthread_mutex_lock(&WaitLock); + lock_grab(&WaitLock); if (AllThreadsShouldSleep || threadID >= ActiveThreads) pthread_cond_wait(&WaitCond, &WaitLock); - pthread_mutex_unlock(&WaitLock); + lock_release(&WaitLock); #else WaitForSingleObject(SitIdleEvent[threadID], INFINITE); #endif @@ -2715,6 +2722,14 @@ namespace { // Initialize global locks lock_init(&MPLock, NULL); + lock_init(&WaitLock, NULL); + +#if !defined(_MSC_VER) + pthread_cond_init(&WaitCond, NULL); +#else + for (i = 0; i < MAX_THREADS; i++) + SitIdleEvent[i] = CreateEvent(0, FALSE, FALSE, 0); +#endif // Initialize SplitPointStack locks for (i = 0; i < MAX_THREADS; i++) @@ -2724,14 +2739,6 @@ namespace { lock_init(&(SplitPointStack[i][j].lock), NULL); } -#if !defined(_MSC_VER) - pthread_mutex_init(&WaitLock, NULL); - pthread_cond_init(&WaitCond, NULL); -#else - for (i = 0; i < MAX_THREADS; i++) - SitIdleEvent[i] = CreateEvent(0, FALSE, FALSE, 0); -#endif - // Will be set just before program exits to properly end the threads AllThreadsShouldExit = false; @@ -2751,8 +2758,7 @@ namespace { #if !defined(_MSC_VER) ok = (pthread_create(pthread, NULL, init_thread, (void*)(&i)) == 0); #else - DWORD iID[1]; - ok = (CreateThread(NULL, 0, init_thread, (LPVOID)(&i), 0, iID) != NULL); + ok = (CreateThread(NULL, 0, init_thread, (LPVOID)(&i), 0, NULL) != NULL); #endif if (!ok) @@ -2787,6 +2793,9 @@ namespace { for (int i = 0; i < MAX_THREADS; i++) for (int j = 0; j < ACTIVE_SPLIT_POINTS_MAX; j++) lock_destroy(&(SplitPointStack[i][j].lock)); + + lock_destroy(&WaitLock); + lock_destroy(&MPLock); } @@ -2991,9 +3000,6 @@ namespace { if (ActiveThreads == 1) return; - for (int i = 1; i < ActiveThreads; i++) - assert(threads[i].state == THREAD_SLEEPING); - #if !defined(_MSC_VER) pthread_mutex_lock(&WaitLock); pthread_cond_broadcast(&WaitCond);