]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Merge branch 'master' into clusterMergeMaster11
[stockfish] / src / search.cpp
index 9c5fb58bd8bbe283cadd3bf7f39ddb8671088ccd..6fc30be2099d4f728b8f478b597655a0ce4199ed 100644 (file)
@@ -23,6 +23,7 @@
 #include <iostream>
 #include <sstream>
 
+#include "cluster.h"
 #include "evaluate.h"
 #include "misc.h"
 #include "movegen.h"
@@ -178,7 +179,7 @@ namespace {
             nodes += cnt;
             pos.undo_move(m);
         }
-        if (Root)
+        if (Root && Cluster::is_root())
             sync_cout << UCI::move(m, pos.is_chess960()) << ": " << cnt << sync_endl;
     }
     return nodes;
@@ -217,7 +218,9 @@ void MainThread::search() {
   if (Limits.perft)
   {
       nodes = perft<true>(rootPos, Limits.perft);
-      sync_cout << "\nNodes searched: " << nodes << "\n" << sync_endl;
+      if (Cluster::is_root())
+          sync_cout << "\nNodes searched: " << nodes << "\n" << sync_endl;
+
       return;
   }
 
@@ -230,9 +233,10 @@ void MainThread::search() {
   if (rootMoves.empty())
   {
       rootMoves.emplace_back(MOVE_NONE);
-      sync_cout << "info depth 0 score "
-                << UCI::value(rootPos.checkers() ? -VALUE_MATE : VALUE_DRAW)
-                << sync_endl;
+      if (Cluster::is_root())
+          sync_cout << "info depth 0 score "
+                    << UCI::value(rootPos.checkers() ? -VALUE_MATE : VALUE_DRAW)
+                    << sync_endl;
   }
   else
   {
@@ -247,19 +251,22 @@ void MainThread::search() {
   // until the GUI sends one of those commands.
 
   while (!Threads.stop && (ponder || Limits.infinite))
-  {} // Busy wait for a stop or a ponder reset
+  { Cluster::signals_poll(); } // Busy wait for a stop or a ponder reset
 
   // Stop the threads if not already stopped (also raise the stop if
   // "ponderhit" just reset Threads.ponder).
   Threads.stop = true;
 
+  // Signal and synchronize all other ranks
+  Cluster::signals_sync();
+
   // Wait until all threads have finished
   Threads.wait_for_search_finished();
 
   // When playing in 'nodes as time' mode, subtract the searched nodes from
   // the available ones before exiting.
   if (Limits.npmsec)
-      Time.availableNodes += Limits.inc[us] - Threads.nodes_searched();
+      Time.availableNodes += Limits.inc[us] - Cluster::nodes_searched();
 
   Thread* bestThread = this;
 
@@ -269,18 +276,40 @@ void MainThread::search() {
       && rootMoves[0].pv[0] != MOVE_NONE)
       bestThread = Threads.get_best_thread();
 
-  bestPreviousScore = bestThread->rootMoves[0].score;
+  // Prepare PVLine and ponder move
+  std::string PVLine = UCI::pv(bestThread->rootPos, bestThread->completedDepth, -VALUE_INFINITE, VALUE_INFINITE);
 
-  // Send again PV info if we have a new best thread
-  if (bestThread != this)
-      sync_cout << UCI::pv(bestThread->rootPos, bestThread->completedDepth, -VALUE_INFINITE, VALUE_INFINITE) << sync_endl;
+  Move bestMove   = bestThread->rootMoves[0].pv[0];
+  Move ponderMove = MOVE_NONE;
+  if (bestThread->rootMoves[0].pv.size() > 1 || bestThread->rootMoves[0].extract_ponder_from_tt(rootPos))
+      ponderMove = bestThread->rootMoves[0].pv[1];
 
-  sync_cout << "bestmove " << UCI::move(bestThread->rootMoves[0].pv[0], rootPos.is_chess960());
+  // Exchange info as needed
+  Cluster::MoveInfo mi{bestMove,
+                       ponderMove,
+                       bestThread->completedDepth,
+                       bestThread->rootMoves[0].score,
+                       Cluster::rank()};
+  Cluster::pick_moves(mi, PVLine);
 
-  if (bestThread->rootMoves[0].pv.size() > 1 || bestThread->rootMoves[0].extract_ponder_from_tt(rootPos))
-      std::cout << " ponder " << UCI::move(bestThread->rootMoves[0].pv[1], rootPos.is_chess960());
+  bestPreviousScore = static_cast<Value>(mi.score);
+
+  if (Cluster::is_root())
+  {
+      // Send again PV info if we have a new best thread/rank
+      if (bestThread != this || mi.rank != 0)
+          sync_cout << PVLine << sync_endl;
+
+      bestMove = static_cast<Move>(mi.move);
+      ponderMove = static_cast<Move>(mi.ponder);
+
+      if (ponderMove != MOVE_NONE)
+          sync_cout << "bestmove " << UCI::move(bestMove, rootPos.is_chess960())
+                    << " ponder "  << UCI::move(ponderMove, rootPos.is_chess960()) << sync_endl;
+      else
+          sync_cout << "bestmove " << UCI::move(bestMove, rootPos.is_chess960()) << sync_endl;
+  }
 
-  std::cout << sync_endl;
 }
 
 
@@ -368,12 +397,13 @@ void Thread::search() {
   // Iterative deepening loop until requested to stop or the target depth is reached
   while (   ++rootDepth < MAX_PLY
          && !Threads.stop
-         && !(Limits.depth && mainThread && rootDepth > Limits.depth))
+         && !(Limits.depth && mainThread && Cluster::is_root() && rootDepth > Limits.depth))
   {
       // Age out PV variability metric
       if (mainThread)
           totBestMoveChanges /= 2;
 
+
       // Save the last iteration's scores before first PV line is searched and
       // all the move scores except the (new) PV are set to -VALUE_INFINITE.
       for (RootMove& rm : rootMoves)
@@ -439,11 +469,15 @@ void Thread::search() {
 
               // When failing high/low give some update (without cluttering
               // the UI) before a re-search.
-              if (   mainThread
+              if (   Cluster::is_root()
+                  && mainThread
                   && multiPV == 1
                   && (bestValue <= alpha || bestValue >= beta)
                   && Time.elapsed() > 3000)
+              {
                   sync_cout << UCI::pv(rootPos, rootDepth, alpha, beta) << sync_endl;
+                  Cluster::cluster_info(rootDepth);
+              }
 
               // In case of failing low/high increase aspiration window and
               // re-search, otherwise exit the loop.
@@ -475,9 +509,12 @@ void Thread::search() {
           // Sort the PV lines searched so far and update the GUI
           std::stable_sort(rootMoves.begin() + pvFirst, rootMoves.begin() + pvIdx + 1);
 
-          if (    mainThread
+          if (    Cluster::is_root() && mainThread
               && (Threads.stop || pvIdx + 1 == multiPV || Time.elapsed() > 3000))
+          {
               sync_cout << UCI::pv(rootPos, rootDepth, alpha, beta) << sync_endl;
+              Cluster::cluster_info(rootDepth);
+          }
       }
 
       if (!Threads.stop)
@@ -748,9 +785,10 @@ namespace {
                 if (    b == BOUND_EXACT
                     || (b == BOUND_LOWER ? value >= beta : value <= alpha))
                 {
-                    tte->save(posKey, value_to_tt(value, ss->ply), ss->ttPv, b,
-                              std::min(MAX_PLY - 1, depth + 6),
-                              MOVE_NONE, VALUE_NONE);
+                    Cluster::save(thisThread, tte,
+                                  posKey, value_to_tt(value, ss->ply), ss->ttPv, b,
+                                  std::min(MAX_PLY - 1, depth + 6),
+                                  MOVE_NONE, VALUE_NONE);
 
                     return value;
                 }
@@ -798,7 +836,9 @@ namespace {
         else
             ss->staticEval = eval = -(ss-1)->staticEval + 2 * Tempo;
 
-        tte->save(posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval);
+        Cluster::save(thisThread, tte,
+                      posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE,
+                      eval);
     }
 
     // Step 7. Razoring (~1 Elo)
@@ -995,7 +1035,7 @@ moves_loop: // When in check, search starts from here
 
       ss->moveCount = ++moveCount;
 
-      if (rootNode && thisThread == Threads.main() && Time.elapsed() > 3000)
+      if (rootNode && Cluster::is_root() && thisThread == Threads.main() && Time.elapsed() > 3000)
           sync_cout << "info depth " << depth
                     << " currmove " << UCI::move(move, pos.is_chess960())
                     << " currmovenumber " << moveCount + thisThread->pvIdx << sync_endl;
@@ -1386,10 +1426,11 @@ moves_loop: // When in check, search starts from here
         ss->ttPv = ss->ttPv && (ss+1)->ttPv;
 
     if (!excludedMove && !(rootNode && thisThread->pvIdx))
-        tte->save(posKey, value_to_tt(bestValue, ss->ply), ss->ttPv,
-                  bestValue >= beta ? BOUND_LOWER :
-                  PvNode && bestMove ? BOUND_EXACT : BOUND_UPPER,
-                  depth, bestMove, ss->staticEval);
+        Cluster::save(thisThread, tte,
+                      posKey, value_to_tt(bestValue, ss->ply), ss->ttPv,
+                      bestValue >= beta ? BOUND_LOWER :
+                      PvNode && bestMove ? BOUND_EXACT : BOUND_UPPER,
+                      depth, bestMove, ss->staticEval);
 
     assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
 
@@ -1486,8 +1527,9 @@ moves_loop: // When in check, search starts from here
         if (bestValue >= beta)
         {
             if (!ss->ttHit)
-                tte->save(posKey, value_to_tt(bestValue, ss->ply), false, BOUND_LOWER,
-                          DEPTH_NONE, MOVE_NONE, ss->staticEval);
+                Cluster::save(thisThread, tte,
+                              posKey, value_to_tt(bestValue, ss->ply), false, BOUND_LOWER,
+                              DEPTH_NONE, MOVE_NONE, ss->staticEval);
 
             return bestValue;
         }
@@ -1608,10 +1650,11 @@ moves_loop: // When in check, search starts from here
     if (ss->inCheck && bestValue == -VALUE_INFINITE)
         return mated_in(ss->ply); // Plies to mate from the root
 
-    tte->save(posKey, value_to_tt(bestValue, ss->ply), pvHit,
-              bestValue >= beta ? BOUND_LOWER :
-              PvNode && bestValue > oldAlpha  ? BOUND_EXACT : BOUND_UPPER,
-              ttDepth, bestMove, ss->staticEval);
+    Cluster::save(thisThread, tte,
+                  posKey, value_to_tt(bestValue, ss->ply), pvHit,
+                  bestValue >= beta ? BOUND_LOWER :
+                  PvNode && bestValue > oldAlpha  ? BOUND_EXACT : BOUND_UPPER,
+                  ttDepth, bestMove, ss->staticEval);
 
     assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
 
@@ -1819,13 +1862,16 @@ void MainThread::check_time() {
       dbg_print();
   }
 
+  // poll on MPI signals
+  Cluster::signals_poll();
+
   // We should not stop pondering until told so by the GUI
   if (ponder)
       return;
 
   if (   (Limits.use_time_management() && (elapsed > Time.maximum() - 10 || stopOnPonderhit))
       || (Limits.movetime && elapsed >= Limits.movetime)
-      || (Limits.nodes && Threads.nodes_searched() >= (uint64_t)Limits.nodes))
+      || (Limits.nodes && Cluster::nodes_searched() >= (uint64_t)Limits.nodes))
       Threads.stop = true;
 }
 
@@ -1840,8 +1886,8 @@ string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) {
   const RootMoves& rootMoves = pos.this_thread()->rootMoves;
   size_t pvIdx = pos.this_thread()->pvIdx;
   size_t multiPV = std::min((size_t)Options["MultiPV"], rootMoves.size());
-  uint64_t nodesSearched = Threads.nodes_searched();
-  uint64_t tbHits = Threads.tb_hits() + (TB::RootInTB ? rootMoves.size() : 0);
+  uint64_t nodesSearched = Cluster::nodes_searched();
+  uint64_t tbHits = Cluster::tb_hits() + (TB::RootInTB ? rootMoves.size() : 0);
 
   for (size_t i = 0; i < multiPV; ++i)
   {