mirror of
https://github.com/sockspls/badfish
synced 2025-04-30 16:53:09 +00:00
Only main thread checks time
The main change of the patch is that now time check is done only by main thread. In the past, before lazy SMP, we needed all the threds to check for available time because main thread could have been blocked on a split point, now this is no more the case and main thread can do the job alone, greatly simplifying the logic. Verified for regression testing on STC with 7 threads: LLR: 2.96 (-2.94,2.94) [-3.00,1.00] Total: 11895 W: 1741 L: 1608 D: 8546 No functional change. Closes #1152
This commit is contained in:
parent
fa1e3427bd
commit
05513a6641
5 changed files with 27 additions and 66 deletions
|
@ -690,7 +690,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
|
||||||
assert(is_ok(m));
|
assert(is_ok(m));
|
||||||
assert(&newSt != st);
|
assert(&newSt != st);
|
||||||
|
|
||||||
++nodes;
|
thisThread->nodes.fetch_add(1, std::memory_order_relaxed);
|
||||||
Key k = st->key ^ Zobrist::side;
|
Key k = st->key ^ Zobrist::side;
|
||||||
|
|
||||||
// Copy some fields of the old state to our new StateInfo object except the
|
// Copy some fields of the old state to our new StateInfo object except the
|
||||||
|
|
|
@ -134,8 +134,6 @@ public:
|
||||||
void undo_move(Move m);
|
void undo_move(Move m);
|
||||||
void do_null_move(StateInfo& newSt);
|
void do_null_move(StateInfo& newSt);
|
||||||
void undo_null_move();
|
void undo_null_move();
|
||||||
void increment_nodes();
|
|
||||||
void increment_tbHits();
|
|
||||||
|
|
||||||
// Static Exchange Evaluation
|
// Static Exchange Evaluation
|
||||||
bool see_ge(Move m, Value threshold = VALUE_ZERO) const;
|
bool see_ge(Move m, Value threshold = VALUE_ZERO) const;
|
||||||
|
@ -152,8 +150,6 @@ public:
|
||||||
int game_ply() const;
|
int game_ply() const;
|
||||||
bool is_chess960() const;
|
bool is_chess960() const;
|
||||||
Thread* this_thread() const;
|
Thread* this_thread() const;
|
||||||
uint64_t nodes_searched() const;
|
|
||||||
uint64_t tb_hits() const;
|
|
||||||
bool is_draw(int ply) const;
|
bool is_draw(int ply) const;
|
||||||
int rule50_count() const;
|
int rule50_count() const;
|
||||||
Score psq_score() const;
|
Score psq_score() const;
|
||||||
|
@ -187,8 +183,6 @@ private:
|
||||||
int castlingRightsMask[SQUARE_NB];
|
int castlingRightsMask[SQUARE_NB];
|
||||||
Square castlingRookSquare[CASTLING_RIGHT_NB];
|
Square castlingRookSquare[CASTLING_RIGHT_NB];
|
||||||
Bitboard castlingPath[CASTLING_RIGHT_NB];
|
Bitboard castlingPath[CASTLING_RIGHT_NB];
|
||||||
uint64_t nodes;
|
|
||||||
uint64_t tbHits;
|
|
||||||
int gamePly;
|
int gamePly;
|
||||||
Color sideToMove;
|
Color sideToMove;
|
||||||
Thread* thisThread;
|
Thread* thisThread;
|
||||||
|
@ -353,22 +347,6 @@ inline int Position::rule50_count() const {
|
||||||
return st->rule50;
|
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 {
|
inline bool Position::opposite_bishops() const {
|
||||||
return pieceCount[W_BISHOP] == 1
|
return pieceCount[W_BISHOP] == 1
|
||||||
&& pieceCount[B_BISHOP] == 1
|
&& pieceCount[B_BISHOP] == 1
|
||||||
|
|
|
@ -154,7 +154,6 @@ namespace {
|
||||||
void update_pv(Move* pv, Move move, Move* childPv);
|
void update_pv(Move* pv, Move move, Move* childPv);
|
||||||
void update_cm_stats(Stack* ss, Piece pc, Square s, int bonus);
|
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 update_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, int bonus);
|
||||||
void check_time();
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -193,7 +192,6 @@ void Search::clear() {
|
||||||
|
|
||||||
for (Thread* th : Threads)
|
for (Thread* th : Threads)
|
||||||
{
|
{
|
||||||
th->resetCalls = true;
|
|
||||||
th->counterMoves.fill(MOVE_NONE);
|
th->counterMoves.fill(MOVE_NONE);
|
||||||
th->history.fill(0);
|
th->history.fill(0);
|
||||||
|
|
||||||
|
@ -204,6 +202,7 @@ void Search::clear() {
|
||||||
th->counterMoveHistory[NO_PIECE][0].fill(CounterMovePruneThreshold - 1);
|
th->counterMoveHistory[NO_PIECE][0].fill(CounterMovePruneThreshold - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Threads.main()->callsCnt = 0;
|
||||||
Threads.main()->previousScore = VALUE_INFINITE;
|
Threads.main()->previousScore = VALUE_INFINITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,9 +399,6 @@ void Thread::search() {
|
||||||
{
|
{
|
||||||
bestValue = ::search<PV>(rootPos, ss, alpha, beta, rootDepth, false, false);
|
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
|
// Bring the best move to the front. It is critical that sorting
|
||||||
// is done with a stable algorithm because all the values but the
|
// is done with a stable algorithm because all the values but the
|
||||||
// first and eventually the new best one are set to -VALUE_INFINITE
|
// first and eventually the new best one are set to -VALUE_INFINITE
|
||||||
|
@ -567,26 +563,8 @@ namespace {
|
||||||
ss->ply = (ss-1)->ply + 1;
|
ss->ply = (ss-1)->ply + 1;
|
||||||
|
|
||||||
// Check for the available remaining time
|
// Check for the available remaining time
|
||||||
if (thisThread->resetCalls.load(std::memory_order_relaxed))
|
if (thisThread == Threads.main())
|
||||||
{
|
static_cast<MainThread*>(thisThread)->check_time();
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used to send selDepth info to GUI
|
// Used to send selDepth info to GUI
|
||||||
if (PvNode && thisThread->maxPly < ss->ply)
|
if (PvNode && thisThread->maxPly < ss->ply)
|
||||||
|
@ -674,7 +652,7 @@ namespace {
|
||||||
|
|
||||||
if (err != TB::ProbeState::FAIL)
|
if (err != TB::ProbeState::FAIL)
|
||||||
{
|
{
|
||||||
pos.increment_tbHits();
|
thisThread->tbHits.fetch_add(1, std::memory_order_relaxed);
|
||||||
|
|
||||||
int drawScore = TB::UseRule50 ? 1 : 0;
|
int drawScore = TB::UseRule50 ? 1 : 0;
|
||||||
|
|
||||||
|
@ -983,7 +961,6 @@ moves_loop: // When in check search starts from here
|
||||||
r -= r ? ONE_PLY : DEPTH_ZERO;
|
r -= r ? ONE_PLY : DEPTH_ZERO;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
// Increase reduction if ttMove is a capture
|
// Increase reduction if ttMove is a capture
|
||||||
if (ttCapture)
|
if (ttCapture)
|
||||||
r += ONE_PLY;
|
r += ONE_PLY;
|
||||||
|
@ -1482,13 +1459,21 @@ moves_loop: // When in check search starts from here
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
// check_time() is used to print debug info and, more importantly, to detect
|
// 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.
|
// when we are out of available time and thus stop the search.
|
||||||
|
|
||||||
void check_time() {
|
void MainThread::check_time() {
|
||||||
|
|
||||||
static std::atomic<TimePoint> 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();
|
int elapsed = Time.elapsed();
|
||||||
TimePoint tick = Limits.startTime + elapsed;
|
TimePoint tick = Limits.startTime + elapsed;
|
||||||
|
@ -1509,8 +1494,6 @@ moves_loop: // When in check search starts from here
|
||||||
Signals.stop = true;
|
Signals.stop = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
|
|
||||||
/// UCI::pv() formats PV information according to the UCI protocol. UCI requires
|
/// 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.
|
/// that all (if any) unsearched PV lines are sent using a previous search score.
|
||||||
|
|
|
@ -34,9 +34,9 @@ ThreadPool Threads; // Global object
|
||||||
|
|
||||||
Thread::Thread() {
|
Thread::Thread() {
|
||||||
|
|
||||||
resetCalls = exit = false;
|
exit = false;
|
||||||
maxPly = callsCnt = 0;
|
maxPly = 0;
|
||||||
tbHits = 0;
|
nodes = tbHits = 0;
|
||||||
idx = Threads.size(); // Start from 0
|
idx = Threads.size(); // Start from 0
|
||||||
|
|
||||||
std::unique_lock<Mutex> lk(mutex);
|
std::unique_lock<Mutex> lk(mutex);
|
||||||
|
@ -163,7 +163,7 @@ uint64_t ThreadPool::nodes_searched() const {
|
||||||
|
|
||||||
uint64_t nodes = 0;
|
uint64_t nodes = 0;
|
||||||
for (Thread* th : *this)
|
for (Thread* th : *this)
|
||||||
nodes += th->nodes;
|
nodes += th->nodes.load(std::memory_order_relaxed);
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ uint64_t ThreadPool::tb_hits() const {
|
||||||
|
|
||||||
uint64_t hits = 0;
|
uint64_t hits = 0;
|
||||||
for (Thread* th : *this)
|
for (Thread* th : *this)
|
||||||
hits += th->tbHits;
|
hits += th->tbHits.load(std::memory_order_relaxed);
|
||||||
return hits;
|
return hits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,8 +211,8 @@ void ThreadPool::start_thinking(Position& pos, StateListPtr& states,
|
||||||
for (Thread* th : Threads)
|
for (Thread* th : Threads)
|
||||||
{
|
{
|
||||||
th->maxPly = 0;
|
th->maxPly = 0;
|
||||||
th->tbHits = 0;
|
|
||||||
th->nodes = 0;
|
th->nodes = 0;
|
||||||
|
th->tbHits = 0;
|
||||||
th->rootDepth = DEPTH_ZERO;
|
th->rootDepth = DEPTH_ZERO;
|
||||||
th->rootMoves = rootMoves;
|
th->rootMoves = rootMoves;
|
||||||
th->rootPos.set(pos.fen(), pos.is_chess960(), &setupStates->back(), th);
|
th->rootPos.set(pos.fen(), pos.is_chess960(), &setupStates->back(), th);
|
||||||
|
|
|
@ -60,15 +60,13 @@ public:
|
||||||
Material::Table materialTable;
|
Material::Table materialTable;
|
||||||
Endgames endgames;
|
Endgames endgames;
|
||||||
size_t idx, PVIdx;
|
size_t idx, PVIdx;
|
||||||
int maxPly, callsCnt;
|
int maxPly;
|
||||||
std::atomic<uint64_t> tbHits;
|
std::atomic<uint64_t> nodes, tbHits;
|
||||||
std::atomic<uint64_t> nodes;
|
|
||||||
|
|
||||||
Position rootPos;
|
Position rootPos;
|
||||||
Search::RootMoves rootMoves;
|
Search::RootMoves rootMoves;
|
||||||
std::atomic<Depth> rootDepth;
|
std::atomic<Depth> rootDepth;
|
||||||
Depth completedDepth;
|
Depth completedDepth;
|
||||||
std::atomic_bool resetCalls;
|
|
||||||
CounterMoveStat counterMoves;
|
CounterMoveStat counterMoves;
|
||||||
ButterflyHistory history;
|
ButterflyHistory history;
|
||||||
CounterMoveHistoryStat counterMoveHistory;
|
CounterMoveHistoryStat counterMoveHistory;
|
||||||
|
@ -79,10 +77,12 @@ public:
|
||||||
|
|
||||||
struct MainThread : public Thread {
|
struct MainThread : public Thread {
|
||||||
virtual void search();
|
virtual void search();
|
||||||
|
void check_time();
|
||||||
|
|
||||||
bool easyMovePlayed, failedLow;
|
bool easyMovePlayed, failedLow;
|
||||||
double bestMoveChanges;
|
double bestMoveChanges;
|
||||||
Value previousScore;
|
Value previousScore;
|
||||||
|
int callsCnt = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue