From: Marco Costalba Date: Wed, 27 Jan 2010 16:29:34 +0000 (+0100) Subject: Simplify locking in sp_search and sp_search_pv X-Git-Url: https://git.sesse.net/?p=stockfish;a=commitdiff_plain;h=bb968fd42a6e3c14755332f5a4c4829faaf4f9de;hp=307909bed8e86cc90e03ae8b66884d7b73beb814 Simplify locking in sp_search and sp_search_pv Avoid to take the lock two times in a tight sequence, the first in get_next_move() and the second to update sp->moves. Do all with one lock and so retire the now useless locked version of get_next_move(). Also fix some theorical race due to comparison sp->bestValue < sp->beta is done out of lock protection. Finally fix another (harmless but time waster) race that coudl occur because thread_should_stop() is also called outside of lock protection. No functional change. Signed-off-by: Marco Costalba --- diff --git a/src/lock.h b/src/lock.h index 14fcd5d9..b17fb79b 100644 --- a/src/lock.h +++ b/src/lock.h @@ -99,5 +99,9 @@ typedef CRITICAL_SECTION Lock; #endif +static inline bool lock_grab_bool(Lock* x) { + lock_grab(x); + return true; +} #endif // !defined(LOCK_H_INCLUDED) diff --git a/src/movepick.cpp b/src/movepick.cpp index 8d8060b5..16eb1634 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -254,6 +254,8 @@ void MovePicker::score_evasions_or_checks() { /// are no more moves left. /// It picks the move with the biggest score from a list of generated moves taking /// care not to return the tt move if has already been searched previously. +/// Note that this function is not thread safe so should be lock protected by +/// caller when accessed through a shared MovePicker object. Move MovePicker::get_next_move() { @@ -343,17 +345,3 @@ Move MovePicker::get_next_move() { } } -/// A variant of get_next_move() which takes a lock as a parameter, used to -/// prevent multiple threads from picking the same move at a split point. - -Move MovePicker::get_next_move(Lock &lock) { - - lock_grab(&lock); - - // Note that it is safe to call many times - // get_next_move() when phase == PH_STOP - Move m = get_next_move(); - - lock_release(&lock); - return m; -} diff --git a/src/movepick.h b/src/movepick.h index a9a3561a..b2bfb5d1 100644 --- a/src/movepick.h +++ b/src/movepick.h @@ -27,7 +27,6 @@ #include "depth.h" #include "history.h" -#include "lock.h" #include "position.h" @@ -52,7 +51,6 @@ class MovePicker { public: MovePicker(const Position& p, Move ttm, Depth d, const History& h, SearchStack* ss = NULL); Move get_next_move(); - Move get_next_move(Lock& lock); int number_of_evasions() const; private: diff --git a/src/search.cpp b/src/search.cpp index e64b9a7d..c3c2925f 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1874,28 +1874,29 @@ namespace { SearchStack* ss = sp->sstack[threadID]; Value value = -VALUE_INFINITE; Move move; + int moveCount; bool isCheck = pos.is_check(); bool useFutilityPruning = sp->depth < SelectiveDepth && !isCheck; const int FutilityMoveCountMargin = 3 + (1 << (3 * int(sp->depth) / 8)); - while ( sp->bestValue < sp->beta + while ( lock_grab_bool(&(sp->lock)) + && sp->bestValue < sp->beta && !thread_should_stop(threadID) - && (move = sp->mp->get_next_move(sp->lock)) != MOVE_NONE) + && (move = sp->mp->get_next_move()) != MOVE_NONE) { + moveCount = ++sp->moves; + lock_release(&(sp->lock)); + assert(move_is_ok(move)); bool moveIsCheck = pos.move_is_check(move, ci); bool captureOrPromotion = pos.move_is_capture_or_promotion(move); - lock_grab(&(sp->lock)); - int moveCount = ++sp->moves; - lock_release(&(sp->lock)); - ss[sp->ply].currentMove = move; - // Decide the new search depth. + // Decide the new search depth bool dangerous; Depth ext = extension(pos, move, false, captureOrPromotion, moveIsCheck, false, false, &dangerous); Depth newDepth = sp->depth - OnePly + ext; @@ -1982,7 +1983,7 @@ namespace { } } - lock_grab(&(sp->lock)); + /* Here we have the lock still grabbed */ // If this is the master thread and we have been asked to stop because of // a beta cutoff higher up in the tree, stop all slave threads. @@ -2015,24 +2016,25 @@ namespace { CheckInfo ci(pos); SearchStack* ss = sp->sstack[threadID]; Value value = -VALUE_INFINITE; + int moveCount; Move move; - while ( sp->alpha < sp->beta + while ( lock_grab_bool(&(sp->lock)) + && sp->alpha < sp->beta && !thread_should_stop(threadID) - && (move = sp->mp->get_next_move(sp->lock)) != MOVE_NONE) + && (move = sp->mp->get_next_move()) != MOVE_NONE) { - bool moveIsCheck = pos.move_is_check(move, ci); - bool captureOrPromotion = pos.move_is_capture_or_promotion(move); + moveCount = ++sp->moves; + lock_release(&(sp->lock)); assert(move_is_ok(move)); - lock_grab(&(sp->lock)); - int moveCount = ++sp->moves; - lock_release(&(sp->lock)); + bool moveIsCheck = pos.move_is_check(move, ci); + bool captureOrPromotion = pos.move_is_capture_or_promotion(move); ss[sp->ply].currentMove = move; - // Decide the new search depth. + // Decide the new search depth bool dangerous; Depth ext = extension(pos, move, true, captureOrPromotion, moveIsCheck, false, false, &dangerous); Depth newDepth = sp->depth - OnePly + ext; @@ -2131,7 +2133,7 @@ namespace { } } - lock_grab(&(sp->lock)); + /* Here we have the lock still grabbed */ // If this is the master thread and we have been asked to stop because of // a beta cutoff higher up in the tree, stop all slave threads.