mirror of
https://github.com/HChaZZY/Stockfish.git
synced 2025-12-20 09:06:45 +08:00
Use atomics instead of volatile
Rely on well defined behaviour for message passing, instead of volatile. Three versions have been tested, to make sure this wouldn't cause a slowdown on any platform. v1: Sequentially consistent atomics No mesurable regression, despite the extra memory barriers on x86. Even with 15 threads and extreme time pressure, both acting as a magnifying glass: threads=15, tc=2+0.02 ELO: 2.59 +-3.4 (95%) LOS: 93.3% Total: 18132 W: 4113 L: 3978 D: 10041 threads=7, tc=2+0.02 ELO: -1.64 +-3.6 (95%) LOS: 18.8% Total: 16914 W: 4053 L: 4133 D: 8728 v2: Acquire/Release semantics This version generates no extra barriers for x86 (on the hot path). As expected, no regression either, under the same conditions: threads=15, tc=2+0.02 ELO: 2.85 +-3.3 (95%) LOS: 95.4% Total: 19661 W: 4640 L: 4479 D: 10542 threads=7, tc=2+0.02 ELO: 0.23 +-3.5 (95%) LOS: 55.1% Total: 18108 W: 4326 L: 4314 D: 9468 As suggested by Joona, another test at LTC: threads=15, tc=20+0.05 ELO: 0.64 +-2.6 (95%) LOS: 68.3% Total: 20000 W: 3053 L: 3016 D: 13931 v3: Final version: SeqCst/Relaxed threads=15, tc=10+0.1 ELO: 0.87 +-3.9 (95%) LOS: 67.1% Total: 9541 W: 1478 L: 1454 D: 6609 Resolves #474
This commit is contained in:
@@ -37,7 +37,7 @@
|
||||
|
||||
namespace Search {
|
||||
|
||||
volatile SignalsType Signals;
|
||||
SignalsType Signals;
|
||||
LimitsType Limits;
|
||||
StateStackPtr SetupStates;
|
||||
}
|
||||
@@ -581,8 +581,8 @@ namespace {
|
||||
if (!RootNode)
|
||||
{
|
||||
// Step 2. Check for aborted search and immediate draw
|
||||
if (Signals.stop || pos.is_draw() || ss->ply >= MAX_PLY)
|
||||
return ss->ply >= MAX_PLY && !inCheck ? evaluate(pos)
|
||||
if (Signals.stop.load(std::memory_order_relaxed) || pos.is_draw() || ss->ply >= MAX_PLY)
|
||||
return ss->ply >= MAX_PLY && !inCheck ? evaluate(pos)
|
||||
: DrawValue[pos.side_to_move()];
|
||||
|
||||
// Step 3. Mate distance pruning. Even if we mate at the next move our score
|
||||
@@ -841,7 +841,7 @@ moves_loop: // When in check search starts from here
|
||||
|
||||
if (RootNode && thisThread == Threads.main())
|
||||
{
|
||||
Signals.firstRootMove = (moveCount == 1);
|
||||
Signals.firstRootMove = moveCount == 1;
|
||||
|
||||
if (Time.elapsed() > 3000)
|
||||
sync_cout << "info depth " << depth / ONE_PLY
|
||||
@@ -1008,7 +1008,7 @@ moves_loop: // When in check search starts from here
|
||||
// Finished searching the move. If a stop occurred, the return value of
|
||||
// the search cannot be trusted, and we return immediately without
|
||||
// updating best move, PV and TT.
|
||||
if (Signals.stop)
|
||||
if (Signals.stop.load(std::memory_order_relaxed))
|
||||
return VALUE_ZERO;
|
||||
|
||||
if (RootNode)
|
||||
@@ -1577,7 +1577,7 @@ void check_time() {
|
||||
{
|
||||
bool stillAtFirstMove = Signals.firstRootMove
|
||||
&& !Signals.failedLowAtRoot
|
||||
&& elapsed > Time.available() * 75 / 100;
|
||||
&& elapsed > Time.available() * 3 / 4;
|
||||
|
||||
if ( stillAtFirstMove
|
||||
|| elapsed > Time.maximum() - 2 * TimerThread::Resolution)
|
||||
|
||||
Reference in New Issue
Block a user