X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=5a4b56ba45ae2383bed345969d93432db8442f98;hp=a3567d91274b5362ad7972f93c4691a97ffed859;hb=c28b9ef182b4a0c3d0483654ebc2b2aca4fc731c;hpb=d74025a34e7589fcc0ba93b878cd6484108f9088 diff --git a/src/search.cpp b/src/search.cpp index a3567d91..5a4b56ba 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -228,7 +228,10 @@ namespace { const Value EasyMoveMargin = Value(0x200); - /// Global variables + /// Namespace variables + + // Book object + Book OpeningBook; // Iteration counter int Iteration; @@ -256,6 +259,7 @@ namespace { // Multi-threads related variables Depth MinimumSplitDepth; int MaxThreadsPerSplitPoint; + bool UseSleepingMaster; ThreadsManager ThreadsMgr; // Node counters, used only by thread[0] but try to keep in different cache @@ -310,7 +314,7 @@ namespace { void extract_pv_from_tt(const Position& pos, Move bestMove, Move pv[]); #if !defined(_MSC_VER) - void *init_thread(void *threadID); + void* init_thread(void* threadID); #else DWORD WINAPI init_thread(LPVOID threadID); #endif @@ -407,12 +411,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,35 +428,39 @@ 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(); + UseSleepingMaster = Options["Use Sleeping Master"].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); @@ -2144,7 +2152,7 @@ split_point_start: // At split points actual search starts from here #if !defined(_MSC_VER) - void* init_thread(void *threadID) { + void* init_thread(void* threadID) { ThreadsMgr.idle_loop(*(int*)threadID, NULL); return NULL; @@ -2172,6 +2180,9 @@ split_point_start: // At split points actual search starts from here assert(threadID >= 0 && threadID < MAX_THREADS); + int i; + bool allFinished = false; + while (true) { // Slave threads can exit as soon as AllThreadsShouldExit raises, @@ -2187,23 +2198,23 @@ split_point_start: // At split points actual search starts from here // instead of wasting CPU time polling for work. while ( threadID >= ActiveThreads || threads[threadID].state == THREAD_INITIALIZING - || (!sp && threads[threadID].state == THREAD_AVAILABLE)) + || (threads[threadID].state == THREAD_AVAILABLE && (!sp || UseSleepingMaster))) { - assert(!sp); - assert(threadID != 0); - - if (AllThreadsShouldExit) - break; - lock_grab(&MPLock); - // Retest condition under lock protection - if (!( threadID >= ActiveThreads - || threads[threadID].state == THREAD_INITIALIZING - || (!sp && threads[threadID].state == THREAD_AVAILABLE))) + // Test with lock held to avoid races with wake_sleeping_thread() + for (i = 0; sp && i < ActiveThreads && !sp->slaves[i]; i++) {} + allFinished = (i == ActiveThreads); + + // Retest sleep conditions under lock protection + if ( AllThreadsShouldExit + || allFinished + || !( threadID >= ActiveThreads + || threads[threadID].state == THREAD_INITIALIZING + || (threads[threadID].state == THREAD_AVAILABLE && (!sp || UseSleepingMaster)))) { lock_release(&MPLock); - continue; + break; } // Put thread to sleep @@ -2233,14 +2244,19 @@ split_point_start: // At split points actual search starts from here assert(threads[threadID].state == THREAD_SEARCHING); threads[threadID].state = THREAD_AVAILABLE; + + // Wake up master thread so to allow it to return from the idle loop in + // case we are the last slave of the split point. + if (UseSleepingMaster && threadID != tsp->master && threads[tsp->master].state == THREAD_AVAILABLE) + wake_sleeping_thread(tsp->master); } // If this thread is the master of a split point and all slaves have // finished their work at this split point, return from the idle loop. - int i = 0; - for ( ; sp && i < ActiveThreads && !sp->slaves[i]; i++) {} + for (i = 0; sp && i < ActiveThreads && !sp->slaves[i]; i++) {} + allFinished = (i == ActiveThreads); - if (i == ActiveThreads) + if (allFinished) { // Because sp->slaves[] is reset under lock protection, // be sure sp->lock has been released before to return. @@ -2264,7 +2280,7 @@ split_point_start: // At split points actual search starts from here void ThreadsManager::init_threads() { - volatile int i; + int i, arg[MAX_THREADS]; bool ok; // Initialize global locks @@ -2292,15 +2308,15 @@ split_point_start: // At split points actual search starts from here // Launch the helper threads for (i = 1; i < MAX_THREADS; i++) { + arg[i] = i; #if !defined(_MSC_VER) pthread_t pthread[1]; - ok = (pthread_create(pthread, NULL, init_thread, (void*)(&i)) == 0); + ok = (pthread_create(pthread, NULL, init_thread, (void*)(&arg[i])) == 0); pthread_detach(pthread[0]); #else - ok = (CreateThread(NULL, 0, init_thread, (LPVOID)(&i), 0, NULL) != NULL); + ok = (CreateThread(NULL, 0, init_thread, (LPVOID)(&arg[i]), 0, NULL) != NULL); #endif - if (!ok) { cout << "Failed to create thread number " << i << endl; @@ -2448,6 +2464,7 @@ split_point_start: // At split points actual search starts from here // Initialize the split point object splitPoint.parent = masterThread.splitPoint; + splitPoint.master = master; splitPoint.stopRequest = false; splitPoint.ply = ply; splitPoint.depth = depth;