]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Don't wake up threads at the beginning of the search
[stockfish] / src / search.cpp
index fa12ee7109c77ad66b4f02eb8b65acc6379205a8..5706b959f2d9ffeb1e0a121a001a7a44c31b5c3b 100644 (file)
@@ -307,11 +307,7 @@ void Search::think() {
           << endl;
   }
 
-  for (int i = 0; i < Threads.size(); i++)
-  {
-      Threads[i].maxPly = 0;
-      Threads[i].wake_up();
-  }
+  Threads.set_size(Options["Threads"]);
 
   // Set best timer interval to avoid lagging under time pressure. Timer is
   // used to check for remaining available thinking time.
@@ -348,7 +344,7 @@ finalize:
   // but if we are pondering or in infinite search, we shouldn't print the best
   // move before we are told to do so.
   if (!Signals.stop && (Limits.ponder || Limits.infinite))
-      Threads.wait_for_stop_or_ponderhit();
+      Threads[pos.thread()].wait_for_stop_or_ponderhit();
 
   // Best move could be MOVE_NONE when searching on a stalemate position
   cout << "bestmove " << move_to_uci(RootMoves[0].pv[0], Chess960)
@@ -467,7 +463,7 @@ namespace {
         if (SkillLevelEnabled && depth == 1 + SkillLevel)
             skillBest = do_skill_level();
 
-        if (Options["Use Search Log"])
+        if (!Signals.stop && Options["Use Search Log"])
              pv_info_to_log(pos, depth, bestValue, elapsed_time(), &RootMoves[0].pv[0]);
 
         // Filter out startup noise when monitoring best move stability
@@ -1061,7 +1057,9 @@ split_point_start: // At split points actual search starts from here
               sp->bestValue = value;
               sp->ss->bestMove = move;
               sp->alpha = alpha;
-              sp->is_betaCutoff = (value >= beta);
+
+              if (value >= beta)
+                  sp->cutoff = true;
           }
       }
 
@@ -1282,12 +1280,7 @@ split_point_start: // At split points actual search starts from here
           && !pos.is_capture_or_promotion(move)
           &&  ss->eval + PawnValueMidgame / 4 < beta
           && !check_is_dangerous(pos, move, futilityBase, beta, &bestValue))
-      {
-          if (ss->eval + PawnValueMidgame / 4 > bestValue)
-              bestValue = ss->eval + PawnValueMidgame / 4;
-
           continue;
-      }
 
       // Check for legality only before to do the move
       if (!pos.pl_move_is_legal(move, ci.pinned))
@@ -1363,8 +1356,7 @@ split_point_start: // At split points actual search starts from here
         return true;
 
     // Rule 2. Queen contact check is very dangerous
-    if (   type_of(pc) == QUEEN
-        && bit_is_set(kingAtt, to))
+    if (type_of(pc) == QUEEN && (kingAtt & to))
         return true;
 
     // Rule 3. Creating new double threats with checks
@@ -1419,23 +1411,21 @@ split_point_start: // At split points actual search starts from here
 
     // Case 3: Moving through the vacated square
     p2 = pos.piece_on(f2);
-    if (   piece_is_slider(p2)
-        && bit_is_set(squares_between(f2, t2), f1))
+    if (piece_is_slider(p2) && (squares_between(f2, t2) & f1))
       return true;
 
     // Case 4: The destination square for m2 is defended by the moving piece in m1
     p1 = pos.piece_on(t1);
-    if (bit_is_set(pos.attacks_from(p1, t1), t2))
+    if (pos.attacks_from(p1, t1) & t2)
         return true;
 
     // Case 5: Discovered check, checking piece is the piece moved in m1
     ksq = pos.king_square(pos.side_to_move());
-    if (    piece_is_slider(p1)
-        &&  bit_is_set(squares_between(t1, ksq), f2))
+    if (piece_is_slider(p1) && (squares_between(t1, ksq) & f2))
     {
         Bitboard occ = pos.occupied_squares();
-        xor_bit(&occ, f2);
-        if (bit_is_set(pos.attacks_from(p1, t1, occ), ksq))
+        occ ^= f2;
+        if (pos.attacks_from(p1, t1, occ) & ksq)
             return true;
     }
     return false;
@@ -1505,9 +1495,9 @@ split_point_start: // At split points actual search starts from here
 
     // Case 3: If the moving piece in the threatened move is a slider, don't
     // prune safe moves which block its ray.
-    if (   piece_is_slider(pos.piece_on(tfrom))
-        && bit_is_set(squares_between(tfrom, tto), mto)
-        && pos.see_sign(m) >= 0)
+    if (    piece_is_slider(pos.piece_on(tfrom))
+        && (squares_between(tfrom, tto) & mto)
+        &&  pos.see_sign(m) >= 0)
         return true;
 
     return false;
@@ -1872,10 +1862,16 @@ void Thread::idle_loop(SplitPoint* sp_master) {
       {
           assert(!do_sleep && !do_exit);
 
-          // Copy split point position and search stack and call search()
-          Stack ss[MAX_PLY_PLUS_2];
+          lock_grab(Threads.splitLock);
+
+          assert(is_searching);
           SplitPoint* sp = splitPoint;
+
+          lock_release(Threads.splitLock);
+
+          Stack ss[MAX_PLY_PLUS_2];
           Position pos(*sp->pos, threadID);
+          int master = sp->master;
 
           memcpy(ss, sp->ss - 1, 4 * sizeof(Stack));
           (ss+1)->sp = sp;
@@ -1893,21 +1889,26 @@ void Thread::idle_loop(SplitPoint* sp_master) {
 
           assert(is_searching);
 
-          // We return from search with lock held
+          is_searching = false;
           sp->slavesMask &= ~(1ULL << threadID);
           sp->nodes += pos.nodes_searched();
-          lock_release(sp->lock);
 
-          is_searching = false;
+          // After releasing the lock we cannot access anymore any SplitPoint
+          // related data in a reliably way becuase it could have been released
+          // under our feet by the sp master.
+          lock_release(sp->lock);
 
           // 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 (   Threads.use_sleeping_threads()
-              && threadID != sp->master
-              && !Threads[sp->master].is_searching)
-              Threads[sp->master].wake_up();
+              && threadID != master
+              && !Threads[master].is_searching)
+              Threads[master].wake_up();
       }
   }
+  // In helpful master concept a master can help only a sub-tree of its split
+  // point, and because here is all finished is not possible master is booked.
+  assert(!is_searching);
 }