X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=f7718ce442d50136b9508405bc6f3bdb76e34654;hp=9649c2da76b269d00ae9380e1fbfd4c018883fbb;hb=55297064268e47103f95a1eb8fd8fe80b6aa2887;hpb=d607febb38e65668ffb70e55db40a827b037d8e6 diff --git a/src/search.cpp b/src/search.cpp index 9649c2da..f7718ce4 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -59,6 +59,10 @@ namespace { // Used for debugging SMP code. const bool FakeSplit = false; + // Fast lookup table of sliding pieces indexed by Piece + const bool Slidings[18] = { 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1 }; + inline bool piece_is_slider(Piece p) { return Slidings[p]; } + // ThreadsManager class is used to handle all the threads related stuff in search, // init, starting, parking and, the most important, launching a slave thread at a // split point are what this class does. All the access to shared thread data is @@ -90,7 +94,7 @@ namespace { int ActiveThreads; volatile bool AllThreadsShouldExit; Thread threads[MAX_THREADS]; - Lock MPLock; + Lock MPLock, WaitLock; WaitCondition WaitCond[MAX_THREADS]; }; @@ -228,7 +232,10 @@ namespace { const Value EasyMoveMargin = Value(0x200); - /// Global variables + /// Namespace variables + + // Book object + Book OpeningBook; // Iteration counter int Iteration; @@ -407,12 +414,12 @@ bool think(Position& pos, bool infinite, bool ponder, int time[], int increment[ UseTimeManagement = !ExactMaxTime && !MaxDepth && !MaxNodes && !InfiniteSearch; // Look for a book move, only during games, not tests - if (UseTimeManagement && get_option_value_bool("OwnBook")) + if (UseTimeManagement && Options["OwnBook"].value()) { - if (get_option_value_string("Book File") != OpeningBook.file_name()) - OpeningBook.open(get_option_value_string("Book File")); + if (Options["Book File"].value() != OpeningBook.file_name()) + OpeningBook.open(Options["Book File"].value()); - Move bookMove = OpeningBook.get_move(pos, get_option_value_bool("Best Book Move")); + Move bookMove = OpeningBook.get_move(pos, Options["Best Book Move"].value()); if (bookMove != MOVE_NONE) { if (PonderSearch) @@ -424,41 +431,48 @@ bool think(Position& pos, bool infinite, bool ponder, int time[], int increment[ } // Read UCI option values - TT.set_size(get_option_value_int("Hash")); - if (button_was_pressed("Clear Hash")) + TT.set_size(Options["Hash"].value()); + if (Options["Clear Hash"].value()) + { + Options["Clear Hash"].set_value("false"); TT.clear(); + } - CheckExtension[1] = Depth(get_option_value_int("Check Extension (PV nodes)")); - CheckExtension[0] = Depth(get_option_value_int("Check Extension (non-PV nodes)")); - SingleEvasionExtension[1] = Depth(get_option_value_int("Single Evasion Extension (PV nodes)")); - SingleEvasionExtension[0] = Depth(get_option_value_int("Single Evasion Extension (non-PV nodes)")); - PawnPushTo7thExtension[1] = Depth(get_option_value_int("Pawn Push to 7th Extension (PV nodes)")); - PawnPushTo7thExtension[0] = Depth(get_option_value_int("Pawn Push to 7th Extension (non-PV nodes)")); - PassedPawnExtension[1] = Depth(get_option_value_int("Passed Pawn Extension (PV nodes)")); - PassedPawnExtension[0] = Depth(get_option_value_int("Passed Pawn Extension (non-PV nodes)")); - PawnEndgameExtension[1] = Depth(get_option_value_int("Pawn Endgame Extension (PV nodes)")); - PawnEndgameExtension[0] = Depth(get_option_value_int("Pawn Endgame Extension (non-PV nodes)")); - 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)")); - - MinimumSplitDepth = get_option_value_int("Minimum Split Depth") * ONE_PLY; - MaxThreadsPerSplitPoint = get_option_value_int("Maximum Number of Threads per Split Point"); - MultiPV = get_option_value_int("MultiPV"); - UseLogFile = get_option_value_bool("Use Search Log"); + CheckExtension[1] = Options["Check Extension (PV nodes)"].value(); + CheckExtension[0] = Options["Check Extension (non-PV nodes)"].value(); + SingleEvasionExtension[1] = Options["Single Evasion Extension (PV nodes)"].value(); + SingleEvasionExtension[0] = Options["Single Evasion Extension (non-PV nodes)"].value(); + PawnPushTo7thExtension[1] = Options["Pawn Push to 7th Extension (PV nodes)"].value(); + PawnPushTo7thExtension[0] = Options["Pawn Push to 7th Extension (non-PV nodes)"].value(); + PassedPawnExtension[1] = Options["Passed Pawn Extension (PV nodes)"].value(); + PassedPawnExtension[0] = Options["Passed Pawn Extension (non-PV nodes)"].value(); + PawnEndgameExtension[1] = Options["Pawn Endgame Extension (PV nodes)"].value(); + PawnEndgameExtension[0] = Options["Pawn Endgame Extension (non-PV nodes)"].value(); + MateThreatExtension[1] = Options["Mate Threat Extension (PV nodes)"].value(); + MateThreatExtension[0] = Options["Mate Threat Extension (non-PV nodes)"].value(); + + MinimumSplitDepth = Options["Minimum Split Depth"].value() * ONE_PLY; + MaxThreadsPerSplitPoint = Options["Maximum Number of Threads per Split Point"].value(); + MultiPV = Options["MultiPV"].value(); + UseLogFile = Options["Use Search Log"].value(); if (UseLogFile) - LogFile.open(get_option_value_string("Search Log Filename").c_str(), std::ios::out | std::ios::app); + LogFile.open(Options["Search Log Filename"].value().c_str(), std::ios::out | std::ios::app); read_weights(pos.side_to_move()); // Set the number of active threads - int newActiveThreads = get_option_value_int("Threads"); + int newActiveThreads = Options["Threads"].value(); if (newActiveThreads != ThreadsMgr.active_threads()) { ThreadsMgr.set_active_threads(newActiveThreads); init_eval(ThreadsMgr.active_threads()); } + // Wake up needed threads + for (int i = 1; i < newActiveThreads; i++) + ThreadsMgr.wake_sleeping_thread(i); + // Set thinking time int myTime = time[pos.side_to_move()]; int myIncrement = increment[pos.side_to_move()]; @@ -491,6 +505,9 @@ bool think(Position& pos, bool infinite, bool ponder, int time[], int increment[ if (UseLogFile) LogFile.close(); + // This makes all the threads to go to sleep + ThreadsMgr.set_active_threads(1); + return !Quit; } @@ -644,7 +661,7 @@ namespace { << " time " << current_search_time() << endl; // Print the best move and the ponder move to the standard output - if (pv[0] == MOVE_NONE) + if (pv[0] == MOVE_NONE || MultiPV > 1) { pv[0] = rml.move(0); pv[1] = MOVE_NONE; @@ -1270,6 +1287,17 @@ split_point_start: // At split points actual search starts from here continue; } + + // Prune neg. see moves at low depths + if ( predictedDepth < 2 * ONE_PLY + && bestValue > value_mated_in(PLY_MAX) + && pos.see_sign(move) < 0) + { + if (SpNode) + lock_grab(&(sp->lock)); + + continue; + } } // Step 13. Make the move @@ -1924,7 +1952,7 @@ split_point_start: // At split points actual search starts from here int t = current_search_time(); // Poll for input - if (Bioskey()) + if (data_available()) { // We are line oriented, don't read single chars std::string command; @@ -2185,9 +2213,7 @@ split_point_start: // At split points actual search starts from here // If we are not thinking, wait for a condition to be signaled // instead of wasting CPU time polling for work. - while ( threadID >= ActiveThreads - || threads[threadID].state == THREAD_INITIALIZING - || (!sp && threads[threadID].state == THREAD_AVAILABLE)) + while (threadID >= ActiveThreads || threads[threadID].state == THREAD_INITIALIZING) { assert(!sp); assert(threadID != 0); @@ -2195,21 +2221,14 @@ split_point_start: // At split points actual search starts from here if (AllThreadsShouldExit) break; - lock_grab(&MPLock); + threads[threadID].state = THREAD_AVAILABLE; - // Retest condition under lock protection - if (!( threadID >= ActiveThreads - || threads[threadID].state == THREAD_INITIALIZING - || (!sp && threads[threadID].state == THREAD_AVAILABLE))) - { - lock_release(&MPLock); - continue; - } + lock_grab(&WaitLock); - // Put thread to sleep - threads[threadID].state = THREAD_AVAILABLE; - cond_wait(&WaitCond[threadID], &MPLock); - lock_release(&MPLock); + if (threadID >= ActiveThreads || threads[threadID].state == THREAD_INITIALIZING) + cond_wait(&WaitCond[threadID], &WaitLock); + + lock_release(&WaitLock); } // If this thread has been assigned work, launch a search @@ -2269,6 +2288,7 @@ split_point_start: // At split points actual search starts from here // Initialize global locks lock_init(&MPLock); + lock_init(&WaitLock); for (i = 0; i < MAX_THREADS; i++) cond_init(&WaitCond[i]); @@ -2304,7 +2324,7 @@ split_point_start: // At split points actual search starts from here if (!ok) { cout << "Failed to create thread number " << i << endl; - Application::exit_with_failure(); + exit(EXIT_FAILURE); } // Wait until the thread has finished launching and is gone to sleep @@ -2332,6 +2352,7 @@ split_point_start: // At split points actual search starts from here for (int j = 0; j < MAX_ACTIVE_SPLIT_POINTS; j++) lock_destroy(&(threads[i].splitPoints[j].lock)); + lock_destroy(&WaitLock); lock_destroy(&MPLock); // Now we can safely destroy the wait conditions @@ -2497,8 +2518,6 @@ split_point_start: // At split points actual search starts from here assert(i == master || threads[i].state == THREAD_BOOKED); threads[i].state = THREAD_WORKISWAITING; // This makes the slave to exit from idle_loop() - if (i != master) - wake_sleeping_thread(i); } // Everything is set up. The master thread enters the idle loop, from @@ -2527,9 +2546,9 @@ split_point_start: // At split points actual search starts from here void ThreadsManager::wake_sleeping_thread(int threadID) { - lock_grab(&MPLock); + lock_grab(&WaitLock); cond_signal(&WaitCond[threadID]); - lock_release(&MPLock); + lock_release(&WaitLock); }