diff --git a/src/position.cpp b/src/position.cpp index 67cf2a02..5df07a09 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -690,7 +690,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) { assert(is_ok(m)); assert(&newSt != st); - ++nodes; + thisThread->nodes.fetch_add(1, std::memory_order_relaxed); Key k = st->key ^ Zobrist::side; // Copy some fields of the old state to our new StateInfo object except the diff --git a/src/position.h b/src/position.h index 8342df3c..22afb3e1 100644 --- a/src/position.h +++ b/src/position.h @@ -134,8 +134,6 @@ public: void undo_move(Move m); void do_null_move(StateInfo& newSt); void undo_null_move(); - void increment_nodes(); - void increment_tbHits(); // Static Exchange Evaluation bool see_ge(Move m, Value threshold = VALUE_ZERO) const; @@ -152,8 +150,6 @@ public: int game_ply() const; bool is_chess960() const; Thread* this_thread() const; - uint64_t nodes_searched() const; - uint64_t tb_hits() const; bool is_draw(int ply) const; int rule50_count() const; Score psq_score() const; @@ -187,8 +183,6 @@ private: int castlingRightsMask[SQUARE_NB]; Square castlingRookSquare[CASTLING_RIGHT_NB]; Bitboard castlingPath[CASTLING_RIGHT_NB]; - uint64_t nodes; - uint64_t tbHits; int gamePly; Color sideToMove; Thread* thisThread; @@ -353,22 +347,6 @@ inline int Position::rule50_count() const { return st->rule50; } -inline uint64_t Position::nodes_searched() const { - return nodes; -} - -inline void Position::increment_nodes() { - nodes++; -} - -inline uint64_t Position::tb_hits() const { - return tbHits; -} - -inline void Position::increment_tbHits() { - tbHits++; -} - inline bool Position::opposite_bishops() const { return pieceCount[W_BISHOP] == 1 && pieceCount[B_BISHOP] == 1 diff --git a/src/search.cpp b/src/search.cpp index 12cbffe0..e6c3cd70 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -154,7 +154,6 @@ namespace { void update_pv(Move* pv, Move move, Move* childPv); void update_cm_stats(Stack* ss, Piece pc, Square s, int bonus); void update_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, int bonus); - void check_time(); } // namespace @@ -193,7 +192,6 @@ void Search::clear() { for (Thread* th : Threads) { - th->resetCalls = true; th->counterMoves.fill(MOVE_NONE); th->history.fill(0); @@ -204,6 +202,7 @@ void Search::clear() { th->counterMoveHistory[NO_PIECE][0].fill(CounterMovePruneThreshold - 1); } + Threads.main()->callsCnt = 0; Threads.main()->previousScore = VALUE_INFINITE; } @@ -400,9 +399,6 @@ void Thread::search() { { bestValue = ::search(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 @@ -567,26 +563,8 @@ namespace { ss->ply = (ss-1)->ply + 1; // Check for the available remaining time - if (thisThread->resetCalls.load(std::memory_order_relaxed)) - { - 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)) - : 4096; - } - - if (--thisThread->callsCnt <= 0) - { - for (Thread* th : Threads) - th->resetCalls = true; - - check_time(); - } + if (thisThread == Threads.main()) + static_cast(thisThread)->check_time(); // Used to send selDepth info to GUI if (PvNode && thisThread->maxPly < ss->ply) @@ -674,7 +652,7 @@ namespace { if (err != TB::ProbeState::FAIL) { - pos.increment_tbHits(); + thisThread->tbHits.fetch_add(1, std::memory_order_relaxed); int drawScore = TB::UseRule50 ? 1 : 0; @@ -960,7 +938,7 @@ moves_loop: // When in check search starts from here ss->moveCount = --moveCount; continue; } - + if (move == ttMove && captureOrPromotion) ttCapture = true; @@ -983,11 +961,10 @@ moves_loop: // When in check search starts from here r -= r ? ONE_PLY : DEPTH_ZERO; else { - // Increase reduction if ttMove is a capture if (ttCapture) r += ONE_PLY; - + // Increase reduction for cut nodes if (cutNode) r += 2 * ONE_PLY; @@ -1482,13 +1459,21 @@ moves_loop: // When in check search starts from here return best; } +} // namespace // check_time() is used to print debug info and, more importantly, to detect // when we are out of available time and thus stop the search. - void check_time() { + void MainThread::check_time() { - static std::atomic lastInfoTime = { now() }; + if (--callsCnt > 0) + return; + + // At low node count increase the checking rate to about 0.1% of nodes + // otherwise use a default value. + callsCnt = Limits.nodes ? std::min(4096, int(Limits.nodes / 1024)) : 4096; + + static TimePoint lastInfoTime = now(); int elapsed = Time.elapsed(); TimePoint tick = Limits.startTime + elapsed; @@ -1509,8 +1494,6 @@ moves_loop: // When in check search starts from here Signals.stop = true; } -} // namespace - /// UCI::pv() formats PV information according to the UCI protocol. UCI requires /// that all (if any) unsearched PV lines are sent using a previous search score. diff --git a/src/thread.cpp b/src/thread.cpp index c80b9bd1..b4e9f8aa 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -34,9 +34,9 @@ ThreadPool Threads; // Global object Thread::Thread() { - resetCalls = exit = false; - maxPly = callsCnt = 0; - tbHits = 0; + exit = false; + maxPly = 0; + nodes = tbHits = 0; idx = Threads.size(); // Start from 0 std::unique_lock lk(mutex); @@ -163,7 +163,7 @@ uint64_t ThreadPool::nodes_searched() const { uint64_t nodes = 0; for (Thread* th : *this) - nodes += th->nodes; + nodes += th->nodes.load(std::memory_order_relaxed); return nodes; } @@ -174,7 +174,7 @@ uint64_t ThreadPool::tb_hits() const { uint64_t hits = 0; for (Thread* th : *this) - hits += th->tbHits; + hits += th->tbHits.load(std::memory_order_relaxed); return hits; } @@ -211,8 +211,8 @@ void ThreadPool::start_thinking(Position& pos, StateListPtr& states, for (Thread* th : Threads) { th->maxPly = 0; - th->tbHits = 0; th->nodes = 0; + th->tbHits = 0; th->rootDepth = DEPTH_ZERO; th->rootMoves = rootMoves; th->rootPos.set(pos.fen(), pos.is_chess960(), &setupStates->back(), th); diff --git a/src/thread.h b/src/thread.h index 0f117c2d..c254047c 100644 --- a/src/thread.h +++ b/src/thread.h @@ -60,15 +60,13 @@ public: Material::Table materialTable; Endgames endgames; size_t idx, PVIdx; - int maxPly, callsCnt; - std::atomic tbHits; - std::atomic nodes; + int maxPly; + std::atomic nodes, tbHits; Position rootPos; Search::RootMoves rootMoves; std::atomic rootDepth; Depth completedDepth; - std::atomic_bool resetCalls; CounterMoveStat counterMoves; ButterflyHistory history; CounterMoveHistoryStat counterMoveHistory; @@ -79,10 +77,12 @@ public: struct MainThread : public Thread { virtual void search(); + void check_time(); bool easyMovePlayed, failedLow; double bestMoveChanges; Value previousScore; + int callsCnt = 0; };