]> git.sesse.net Git - stockfish/commitdiff
Allow split point master to sleep (take 2)
authorMarco Costalba <mcostalba@gmail.com>
Sun, 7 Nov 2010 22:45:13 +0000 (23:45 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Sun, 7 Nov 2010 22:51:09 +0000 (23:51 +0100)
Let to sleep even split point master, it will be waken
up by its slaves when they return from the search.

This time let it be enabled by an UCI option, so
people is free to test it on their Hyper Thread box.

Option is disabled by default.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
src/search.cpp
src/thread.h
src/ucioption.cpp

index 59c717caa9700e5412b9de78101d791dcd42c6d5..5a4b56ba45ae2383bed345969d93432db8442f98 100644 (file)
@@ -259,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
@@ -451,6 +452,7 @@ bool think(Position& pos, bool infinite, bool ponder, int time[], int increment[
   MaxThreadsPerSplitPoint = Options["Maximum Number of Threads per Split Point"].value<int>();
   MultiPV                 = Options["MultiPV"].value<int>();
   UseLogFile              = Options["Use Search Log"].value<bool>();
+  UseSleepingMaster       = Options["Use Sleeping Master"].value<bool>();
 
   if (UseLogFile)
       LogFile.open(Options["Search Log Filename"].value<std::string>().c_str(), std::ios::out | std::ios::app);
@@ -2178,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,
@@ -2193,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
@@ -2239,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.
@@ -2454,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;
index 44b70e1e64311e910f7e4cb2cfd61b7939535214..98576ccea2131a877edc2a61a16ff164219596c3 100644 (file)
@@ -55,6 +55,7 @@ struct SplitPoint {
   bool pvNode, mateThreat;
   Value beta;
   int ply;
+  int master;
   Move threatMove;
   SearchStack sstack[MAX_THREADS][PLY_MAX_PLUS_2];
 
index b1b849807ff507c792198a4855dc9d5d1b9a61c0..760d7df21561868a393f7ea4110ea309cda26040 100644 (file)
@@ -74,6 +74,7 @@ void init_uci_options() {
   Options["Minimum Split Depth"] = Option(4, 4, 7);
   Options["Maximum Number of Threads per Split Point"] = Option(5, 4, 8);
   Options["Threads"] = Option(1, 1, MAX_THREADS);
+  Options["Use Sleeping Master"] = Option(false);
   Options["Hash"] = Option(32, 4, 8192);
   Options["Clear Hash"] = Option(false, "button");
   Options["New Game"] = Option(false, "button");