mirror of
https://github.com/HChaZZY/Stockfish.git
synced 2025-12-22 01:56:58 +08:00
Get rid of timer thread
Unfortunately std::condition_variable::wait_for() is not accurate in general case and the timer thread can wake up also after tens or even hundreds of millisecs after time has elapsded. CPU load, process priorities, number of concurrent threads, even from other processes, will have effect upon it. Even official documentation says: "This function may block for longer than timeout_duration due to scheduling or resource contention delays." So retire timer and use a polling scheme based on a local thread counter that counts search() calls and a small trick to keep polling frequency constant, independently from the number of threads. Tested for no regression at very fast TC 2+0.05 th 7: LLR: 2.96 (-2.94,2.94) [-3.00,1.00] Total: 32969 W: 6720 L: 6620 D: 19629 TC 2+0.05 th 1: LLR: 2.95 (-2.94,2.94) [-3.00,1.00] Total: 7765 W: 1917 L: 1765 D: 4083 And at STC TC, both single thread LLR: 2.96 (-2.94,2.94) [-3.00,1.00] Total: 15587 W: 3036 L: 2905 D: 9646 And with 7 threads LLR: 2.95 (-2.94,2.94) [-3.00,1.00] Total: 8149 W: 1367 L: 1227 D: 5555 bench: 8639247
This commit is contained in:
28
src/thread.h
28
src/thread.h
@@ -44,12 +44,12 @@ struct ThreadBase : public std::thread {
|
||||
virtual ~ThreadBase() = default;
|
||||
virtual void idle_loop() = 0;
|
||||
void notify_one();
|
||||
void wait(std::atomic<bool>& b);
|
||||
void wait_while(std::atomic<bool>& b);
|
||||
void wait(std::atomic_bool& b);
|
||||
void wait_while(std::atomic_bool& b);
|
||||
|
||||
Mutex mutex;
|
||||
ConditionVariable sleepCondition;
|
||||
std::atomic<bool> exit;
|
||||
std::atomic_bool exit;
|
||||
};
|
||||
|
||||
|
||||
@@ -68,8 +68,8 @@ struct Thread : public ThreadBase {
|
||||
Material::Table materialTable;
|
||||
Endgames endgames;
|
||||
size_t idx, PVIdx;
|
||||
int maxPly;
|
||||
std::atomic<bool> searching;
|
||||
int maxPly, callsCnt;
|
||||
std::atomic_bool searching, resetCallsCnt;
|
||||
|
||||
Position rootPos;
|
||||
Search::RootMoveVector rootMoves;
|
||||
@@ -80,25 +80,14 @@ struct Thread : public ThreadBase {
|
||||
};
|
||||
|
||||
|
||||
/// MainThread and TimerThread are derived classes used to characterize the two
|
||||
/// special threads: the main one and the recurring timer.
|
||||
/// MainThread is a derived classes used to characterize the the main one
|
||||
|
||||
struct MainThread : public Thread {
|
||||
MainThread() { thinking = true; } // Avoid a race with start_thinking()
|
||||
virtual void idle_loop();
|
||||
void join();
|
||||
void think();
|
||||
std::atomic<bool> thinking;
|
||||
};
|
||||
|
||||
struct TimerThread : public ThreadBase {
|
||||
|
||||
static const int Resolution = 5; // Millisec between two check_time() calls
|
||||
|
||||
virtual void idle_loop();
|
||||
void check_time();
|
||||
|
||||
bool run = false;
|
||||
std::atomic_bool thinking;
|
||||
};
|
||||
|
||||
|
||||
@@ -108,14 +97,13 @@ struct TimerThread : public ThreadBase {
|
||||
|
||||
struct ThreadPool : public std::vector<Thread*> {
|
||||
|
||||
void init(); // No constructor and destructor, threads rely on globals that should
|
||||
void init(); // No constructor and destructor, threads rely on globals that should
|
||||
void exit(); // be initialized and valid during the whole thread lifetime.
|
||||
|
||||
MainThread* main() { return static_cast<MainThread*>(at(0)); }
|
||||
void read_uci_options();
|
||||
void start_thinking(const Position&, const Search::LimitsType&, Search::StateStackPtr&);
|
||||
int64_t nodes_searched();
|
||||
TimerThread* timer;
|
||||
};
|
||||
|
||||
extern ThreadPool Threads;
|
||||
|
||||
Reference in New Issue
Block a user