mirror of
https://github.com/opelly27/Stockfish.git
synced 2026-05-20 10:57:43 +00:00
Fix four data races.
the nodes, tbHits, rootDepth and lastInfoTime variables are read by multiple threads, but not declared atomic, leading to data races as found by -fsanitize=thread. This patch fixes this issue. It is based on top of the CI-threading branch (PR #1129), and should fix the corresponding CI error messages. The patch passed an STC check for no regression: http://tests.stockfishchess.org/tests/view/5925d5590ebc59035df34b9f LLR: 2.96 (-2.94,2.94) [-3.00,1.00] Total: 169597 W: 29938 L: 30066 D: 109593 Whereas rootDepth and lastInfoTime are not performance critical, nodes and tbHits are. Indeed, an earlier version using relaxed atomic updates on the latter two variables failed STC testing (http://tests.stockfishchess.org/tests/view/592001700ebc59035df34924), which can be shown to be due to x86-32 (http://tests.stockfishchess.org/tests/view/592330ac0ebc59035df34a89). Indeed, the latter have no instruction to atomically update a 64bit variable. The proposed solution thus uses a variable in Position that is accessed only by one thread, which is copied every few thousand nodes to the shared variable in Thread. No functional change. Closes #1130 Closes #1129
This commit is contained in:
committed by
Joona Kiiski
parent
2c237da546
commit
3cb0200459
+9
-3
@@ -361,7 +361,7 @@ void Thread::search() {
|
||||
multiPV = std::min(multiPV, rootMoves.size());
|
||||
|
||||
// Iterative deepening loop until requested to stop or the target depth is reached
|
||||
while ( (rootDepth += ONE_PLY) < DEPTH_MAX
|
||||
while ( (rootDepth = rootDepth + ONE_PLY) < DEPTH_MAX
|
||||
&& !Signals.stop
|
||||
&& (!Limits.depth || Threads.main()->rootDepth / ONE_PLY <= Limits.depth))
|
||||
{
|
||||
@@ -400,6 +400,9 @@ void Thread::search() {
|
||||
{
|
||||
bestValue = ::search<PV>(rootPos, ss, alpha, beta, rootDepth, false, false);
|
||||
|
||||
this->tbHits = rootPos.tb_hits();
|
||||
this->nodes = rootPos.nodes_searched();
|
||||
|
||||
// Bring the best move to the front. It is critical that sorting
|
||||
// is done with a stable algorithm because all the values but the
|
||||
// first and eventually the new best one are set to -VALUE_INFINITE
|
||||
@@ -568,6 +571,9 @@ namespace {
|
||||
{
|
||||
thisThread->resetCalls = false;
|
||||
|
||||
thisThread->tbHits = pos.tb_hits();
|
||||
thisThread->nodes = pos.nodes_searched();
|
||||
|
||||
// At low node count increase the checking rate to about 0.1% of nodes
|
||||
// otherwise use a default value.
|
||||
thisThread->callsCnt = Limits.nodes ? std::min(4096, int(Limits.nodes / 1024))
|
||||
@@ -668,7 +674,7 @@ namespace {
|
||||
|
||||
if (err != TB::ProbeState::FAIL)
|
||||
{
|
||||
thisThread->tbHits++;
|
||||
pos.increment_tbHits();
|
||||
|
||||
int drawScore = TB::UseRule50 ? 1 : 0;
|
||||
|
||||
@@ -1473,7 +1479,7 @@ moves_loop: // When in check search starts from here
|
||||
|
||||
void check_time() {
|
||||
|
||||
static TimePoint lastInfoTime = now();
|
||||
static std::atomic<TimePoint> lastInfoTime = { now() };
|
||||
|
||||
int elapsed = Time.elapsed();
|
||||
TimePoint tick = Limits.startTime + elapsed;
|
||||
|
||||
Reference in New Issue
Block a user