From: Marco Costalba Date: Fri, 3 Feb 2012 12:18:51 +0000 (+0100) Subject: Reduce lock contention in idle_loop X-Git-Url: https://git.sesse.net/?p=stockfish;a=commitdiff_plain;h=c94cfebb7e6d787b9bdf2670cc1436eb0dfbea57;hp=57e942145c113e9d1bed7eeef5089dd22eedaad6 Reduce lock contention in idle_loop Release split point lock before to wake up master thread. This seems to increase speed in case "sleeping threads" are used: After 7792 games with 4 threads at very fast TC (2"+0.05) Mod vs Orig 1722 - 1627 - 4443 ELO +4 (+- 5.1) No functional change. Signed-off-by: Marco Costalba --- diff --git a/src/search.cpp b/src/search.cpp index 49a7b4da..8823e98f 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1873,6 +1873,7 @@ void Thread::idle_loop(SplitPoint* sp_master) { 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; @@ -1894,17 +1895,17 @@ void Thread::idle_loop(SplitPoint* sp_master) { sp->slavesMask &= ~(1ULL << threadID); sp->nodes += pos.nodes_searched(); - // 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(); - // 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 != master + && !Threads[master].is_searching) + Threads[master].wake_up(); } } // In helpful master concept a master can help only a sub-tree of its split diff --git a/src/thread.cpp b/src/thread.cpp index 8a8e7199..3eb393bc 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -274,8 +274,8 @@ Value ThreadsManager::split(Position& pos, Stack* ss, Value alpha, Value beta, // Try to allocate available threads and ask them to start searching setting // is_searching flag. This must be done under lock protection to avoid concurrent // allocation of the same slave by another master. + lock_grab(sp->lock); lock_grab(splitLock); - lock_grab(sp->lock); // To protect sp->slaves_mask for (int i = 0; i < activeThreads && !Fake; i++) if (threads[i].is_available_to(master)) @@ -294,8 +294,8 @@ Value ThreadsManager::split(Position& pos, Stack* ss, Value alpha, Value beta, masterThread.splitPoint = sp; masterThread.activeSplitPoints++; - lock_release(sp->lock); lock_release(splitLock); + lock_release(sp->lock); // Everything is set up. The master thread enters the idle loop, from which // it will instantly launch a search, because its is_searching flag is set. @@ -308,16 +308,16 @@ Value ThreadsManager::split(Position& pos, Stack* ss, Value alpha, Value beta, // We have returned from the idle loop, which means that all threads are // finished. Note that setting is_searching and decreasing activeSplitPoints is // done under lock protection to avoid a race with Thread::is_available_to(). - lock_grab(splitLock); lock_grab(sp->lock); // To protect sp->nodes + lock_grab(splitLock); masterThread.is_searching = true; masterThread.activeSplitPoints--; masterThread.splitPoint = sp->parent; pos.set_nodes_searched(pos.nodes_searched() + sp->nodes); - lock_release(sp->lock); lock_release(splitLock); + lock_release(sp->lock); return sp->bestValue; } diff --git a/src/thread.h b/src/thread.h index 10d12014..c93bcb4d 100644 --- a/src/thread.h +++ b/src/thread.h @@ -40,7 +40,6 @@ struct SplitPoint { Depth depth; Value beta; int nodeType; - int ply; int master; Move threatMove;