mirror of
https://github.com/sockspls/badfish
synced 2025-07-11 19:49:14 +00:00
Big renaming in thread stuff
No functional change. Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
parent
c465f4c4df
commit
588670e8d2
6 changed files with 62 additions and 59 deletions
|
@ -130,8 +130,8 @@ void benchmark(const Position& current, istream& is) {
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Threads.start_searching(pos, limits, vector<Move>(), st);
|
Threads.start_thinking(pos, limits, vector<Move>(), st);
|
||||||
Threads.wait_for_search_finished();
|
Threads.wait_for_think_finished();
|
||||||
nodes += Search::RootPos.nodes_searched();
|
nodes += Search::RootPos.nodes_searched();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
/// The checkInfo struct is initialized at c'tor time and keeps info used
|
/// The checkInfo struct is initialized at c'tor time and keeps info used
|
||||||
/// to detect if a move gives check.
|
/// to detect if a move gives check.
|
||||||
class Position;
|
class Position;
|
||||||
class Thread;
|
struct Thread;
|
||||||
|
|
||||||
struct CheckInfo {
|
struct CheckInfo {
|
||||||
|
|
||||||
|
|
|
@ -1007,7 +1007,7 @@ split_point_start: // At split points actual search starts from here
|
||||||
|
|
||||||
// Step 19. Check for splitting the search
|
// Step 19. Check for splitting the search
|
||||||
if ( !SpNode
|
if ( !SpNode
|
||||||
&& depth >= Threads.min_split_depth()
|
&& depth >= Threads.minimumSplitDepth
|
||||||
&& Threads.available_slave_exists(thisThread))
|
&& Threads.available_slave_exists(thisThread))
|
||||||
{
|
{
|
||||||
assert(bestValue < beta);
|
assert(bestValue < beta);
|
||||||
|
@ -1558,7 +1558,7 @@ void Thread::idle_loop() {
|
||||||
// object for which the thread is the master.
|
// object for which the thread is the master.
|
||||||
const SplitPoint* sp_master = splitPointsCnt ? curSplitPoint : NULL;
|
const SplitPoint* sp_master = splitPointsCnt ? curSplitPoint : NULL;
|
||||||
|
|
||||||
assert(!sp_master || (sp_master->master == this && is_searching));
|
assert(!sp_master || (sp_master->master == this && searching));
|
||||||
|
|
||||||
// If this thread is the master of a split point and all slaves have
|
// If this thread is the master of a split point and all slaves have
|
||||||
// finished their work at this split point, return from the idle loop.
|
// finished their work at this split point, return from the idle loop.
|
||||||
|
@ -1566,9 +1566,9 @@ void Thread::idle_loop() {
|
||||||
{
|
{
|
||||||
// If we are not searching, wait for a condition to be signaled
|
// If we are not searching, wait for a condition to be signaled
|
||||||
// instead of wasting CPU time polling for work.
|
// instead of wasting CPU time polling for work.
|
||||||
while (do_exit || (!is_searching && Threads.sleepWhileIdle))
|
while ((!searching && Threads.sleepWhileIdle) || exit)
|
||||||
{
|
{
|
||||||
if (do_exit)
|
if (exit)
|
||||||
{
|
{
|
||||||
assert(!sp_master);
|
assert(!sp_master);
|
||||||
return;
|
return;
|
||||||
|
@ -1588,20 +1588,20 @@ void Thread::idle_loop() {
|
||||||
// particular we need to avoid a deadlock in case a master thread has,
|
// particular we need to avoid a deadlock in case a master thread has,
|
||||||
// in the meanwhile, allocated us and sent the wake_up() call before we
|
// in the meanwhile, allocated us and sent the wake_up() call before we
|
||||||
// had the chance to grab the lock.
|
// had the chance to grab the lock.
|
||||||
if (!is_searching && !do_exit)
|
if (!searching && !exit)
|
||||||
sleepCondition.wait(mutex);
|
sleepCondition.wait(mutex);
|
||||||
|
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this thread has been assigned work, launch a search
|
// If this thread has been assigned work, launch a search
|
||||||
if (is_searching)
|
if (searching)
|
||||||
{
|
{
|
||||||
assert(!do_exit);
|
assert(!exit);
|
||||||
|
|
||||||
Threads.mutex.lock();
|
Threads.mutex.lock();
|
||||||
|
|
||||||
assert(is_searching);
|
assert(searching);
|
||||||
SplitPoint* sp = curSplitPoint;
|
SplitPoint* sp = curSplitPoint;
|
||||||
|
|
||||||
Threads.mutex.unlock();
|
Threads.mutex.unlock();
|
||||||
|
@ -1627,9 +1627,9 @@ void Thread::idle_loop() {
|
||||||
else
|
else
|
||||||
assert(false);
|
assert(false);
|
||||||
|
|
||||||
assert(is_searching);
|
assert(searching);
|
||||||
|
|
||||||
is_searching = false;
|
searching = false;
|
||||||
sp->activePositions[idx] = NULL;
|
sp->activePositions[idx] = NULL;
|
||||||
sp->slavesMask &= ~(1ULL << idx);
|
sp->slavesMask &= ~(1ULL << idx);
|
||||||
sp->nodes += pos.nodes_searched();
|
sp->nodes += pos.nodes_searched();
|
||||||
|
@ -1640,7 +1640,7 @@ void Thread::idle_loop() {
|
||||||
&& this != sp->master
|
&& this != sp->master
|
||||||
&& !sp->slavesMask)
|
&& !sp->slavesMask)
|
||||||
{
|
{
|
||||||
assert(!sp->master->is_searching);
|
assert(!sp->master->searching);
|
||||||
sp->master->notify_one();
|
sp->master->notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace { extern "C" {
|
||||||
|
|
||||||
Thread::Thread() : splitPoints() {
|
Thread::Thread() : splitPoints() {
|
||||||
|
|
||||||
is_searching = do_exit = false;
|
searching = exit = false;
|
||||||
maxPly = splitPointsCnt = 0;
|
maxPly = splitPointsCnt = 0;
|
||||||
curSplitPoint = NULL;
|
curSplitPoint = NULL;
|
||||||
idx = Threads.size();
|
idx = Threads.size();
|
||||||
|
@ -61,7 +61,7 @@ Thread::Thread() : splitPoints() {
|
||||||
|
|
||||||
Thread::~Thread() {
|
Thread::~Thread() {
|
||||||
|
|
||||||
do_exit = true; // Search must be already finished
|
exit = true; // Search must be already finished
|
||||||
notify_one();
|
notify_one();
|
||||||
thread_join(handle); // Wait for thread termination
|
thread_join(handle); // Wait for thread termination
|
||||||
}
|
}
|
||||||
|
@ -73,11 +73,11 @@ extern void check_time();
|
||||||
|
|
||||||
void TimerThread::idle_loop() {
|
void TimerThread::idle_loop() {
|
||||||
|
|
||||||
while (!do_exit)
|
while (!exit)
|
||||||
{
|
{
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
|
|
||||||
if (!do_exit)
|
if (!exit)
|
||||||
sleepCondition.wait_for(mutex, msec ? msec : INT_MAX);
|
sleepCondition.wait_for(mutex, msec ? msec : INT_MAX);
|
||||||
|
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
|
@ -97,10 +97,9 @@ void MainThread::idle_loop() {
|
||||||
{
|
{
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
|
|
||||||
is_finished = true; // Always return to sleep after a search
|
thinking = false;
|
||||||
is_searching = false;
|
|
||||||
|
|
||||||
while (is_finished && !do_exit)
|
while (!thinking && !exit)
|
||||||
{
|
{
|
||||||
Threads.sleepCondition.notify_one(); // Wake up UI thread if needed
|
Threads.sleepCondition.notify_one(); // Wake up UI thread if needed
|
||||||
sleepCondition.wait(mutex);
|
sleepCondition.wait(mutex);
|
||||||
|
@ -108,19 +107,21 @@ void MainThread::idle_loop() {
|
||||||
|
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
|
|
||||||
if (do_exit)
|
if (exit)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
is_searching = true;
|
searching = true;
|
||||||
|
|
||||||
Search::think();
|
Search::think();
|
||||||
|
|
||||||
assert(is_searching);
|
assert(searching);
|
||||||
|
|
||||||
|
searching = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Thread::notify_one() wakes up the thread, normally at split time
|
// Thread::notify_one() wakes up the thread when there is some search to do
|
||||||
|
|
||||||
void Thread::notify_one() {
|
void Thread::notify_one() {
|
||||||
|
|
||||||
|
@ -162,7 +163,7 @@ bool Thread::cutoff_occurred() const {
|
||||||
|
|
||||||
bool Thread::is_available_to(Thread* master) const {
|
bool Thread::is_available_to(Thread* master) const {
|
||||||
|
|
||||||
if (is_searching)
|
if (searching)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Make a local copy to be sure doesn't become zero under our feet while
|
// Make a local copy to be sure doesn't become zero under our feet while
|
||||||
|
@ -283,7 +284,7 @@ Value ThreadPool::split(Position& pos, Stack* ss, Value alpha, Value beta,
|
||||||
sp.nodes = 0;
|
sp.nodes = 0;
|
||||||
sp.ss = ss;
|
sp.ss = ss;
|
||||||
|
|
||||||
assert(master->is_searching);
|
assert(master->searching);
|
||||||
|
|
||||||
master->curSplitPoint = &sp;
|
master->curSplitPoint = &sp;
|
||||||
int slavesCnt = 0;
|
int slavesCnt = 0;
|
||||||
|
@ -299,7 +300,7 @@ Value ThreadPool::split(Position& pos, Stack* ss, Value alpha, Value beta,
|
||||||
{
|
{
|
||||||
sp.slavesMask |= 1ULL << i;
|
sp.slavesMask |= 1ULL << i;
|
||||||
threads[i]->curSplitPoint = &sp;
|
threads[i]->curSplitPoint = &sp;
|
||||||
threads[i]->is_searching = true; // Slave leaves idle_loop()
|
threads[i]->searching = true; // Slave leaves idle_loop()
|
||||||
threads[i]->notify_one(); // Could be sleeping
|
threads[i]->notify_one(); // Could be sleeping
|
||||||
|
|
||||||
if (++slavesCnt + 1 >= maxThreadsPerSplitPoint) // Master is always included
|
if (++slavesCnt + 1 >= maxThreadsPerSplitPoint) // Master is always included
|
||||||
|
@ -321,7 +322,7 @@ Value ThreadPool::split(Position& pos, Stack* ss, Value alpha, Value beta,
|
||||||
|
|
||||||
// In helpful master concept a master can help only a sub-tree of its split
|
// In helpful master concept a master can help only a sub-tree of its split
|
||||||
// point, and because here is all finished is not possible master is booked.
|
// point, and because here is all finished is not possible master is booked.
|
||||||
assert(!master->is_searching);
|
assert(!master->searching);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have returned from the idle loop, which means that all threads are
|
// We have returned from the idle loop, which means that all threads are
|
||||||
|
@ -330,7 +331,7 @@ Value ThreadPool::split(Position& pos, Stack* ss, Value alpha, Value beta,
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
sp.mutex.lock();
|
sp.mutex.lock();
|
||||||
|
|
||||||
master->is_searching = true;
|
master->searching = true;
|
||||||
master->splitPointsCnt--;
|
master->splitPointsCnt--;
|
||||||
master->curSplitPoint = sp.parent;
|
master->curSplitPoint = sp.parent;
|
||||||
pos.set_nodes_searched(pos.nodes_searched() + sp.nodes);
|
pos.set_nodes_searched(pos.nodes_searched() + sp.nodes);
|
||||||
|
@ -347,24 +348,23 @@ template Value ThreadPool::split<false>(Position&, Stack*, Value, Value, Value,
|
||||||
template Value ThreadPool::split<true>(Position&, Stack*, Value, Value, Value, Move*, Depth, Move, int, MovePicker&, int);
|
template Value ThreadPool::split<true>(Position&, Stack*, Value, Value, Value, Move*, Depth, Move, int, MovePicker&, int);
|
||||||
|
|
||||||
|
|
||||||
// wait_for_search_finished() waits for main thread to go to sleep, this means
|
// wait_for_think_finished() waits for main thread to go to sleep then returns
|
||||||
// search is finished. Then returns.
|
|
||||||
|
|
||||||
void ThreadPool::wait_for_search_finished() {
|
void ThreadPool::wait_for_think_finished() {
|
||||||
|
|
||||||
MainThread* t = main_thread();
|
MainThread* t = main_thread();
|
||||||
t->mutex.lock();
|
t->mutex.lock();
|
||||||
while (!t->is_finished) sleepCondition.wait(t->mutex);
|
while (t->thinking) sleepCondition.wait(t->mutex);
|
||||||
t->mutex.unlock();
|
t->mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// start_searching() wakes up the main thread sleeping in main_loop() so to start
|
// start_thinking() wakes up the main thread sleeping in main_loop() so to start
|
||||||
// a new search, then returns immediately.
|
// a new search, then returns immediately.
|
||||||
|
|
||||||
void ThreadPool::start_searching(const Position& pos, const LimitsType& limits,
|
void ThreadPool::start_thinking(const Position& pos, const LimitsType& limits,
|
||||||
const std::vector<Move>& searchMoves, StateStackPtr& states) {
|
const std::vector<Move>& searchMoves, StateStackPtr& states) {
|
||||||
wait_for_search_finished();
|
wait_for_think_finished();
|
||||||
|
|
||||||
SearchTime = Time::now(); // As early as possible
|
SearchTime = Time::now(); // As early as possible
|
||||||
|
|
||||||
|
@ -380,6 +380,6 @@ void ThreadPool::start_searching(const Position& pos, const LimitsType& limits,
|
||||||
if (searchMoves.empty() || count(searchMoves.begin(), searchMoves.end(), ml.move()))
|
if (searchMoves.empty() || count(searchMoves.begin(), searchMoves.end(), ml.move()))
|
||||||
RootMoves.push_back(RootMove(ml.move()));
|
RootMoves.push_back(RootMove(ml.move()));
|
||||||
|
|
||||||
main_thread()->is_finished = false;
|
main_thread()->thinking = true;
|
||||||
main_thread()->notify_one(); // Starts main thread
|
main_thread()->notify_one(); // Starts main thread
|
||||||
}
|
}
|
||||||
|
|
39
src/thread.h
39
src/thread.h
|
@ -56,7 +56,7 @@ private:
|
||||||
WaitCondition c;
|
WaitCondition c;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Thread;
|
struct Thread;
|
||||||
|
|
||||||
struct SplitPoint {
|
struct SplitPoint {
|
||||||
|
|
||||||
|
@ -91,9 +91,8 @@ struct SplitPoint {
|
||||||
/// tables so that once we get a pointer to an entry its life time is unlimited
|
/// tables so that once we get a pointer to an entry its life time is unlimited
|
||||||
/// and we don't have to care about someone changing the entry under our feet.
|
/// and we don't have to care about someone changing the entry under our feet.
|
||||||
|
|
||||||
class Thread {
|
struct Thread {
|
||||||
|
|
||||||
public:
|
|
||||||
Thread();
|
Thread();
|
||||||
virtual ~Thread();
|
virtual ~Thread();
|
||||||
|
|
||||||
|
@ -114,8 +113,18 @@ public:
|
||||||
NativeHandle handle;
|
NativeHandle handle;
|
||||||
SplitPoint* volatile curSplitPoint;
|
SplitPoint* volatile curSplitPoint;
|
||||||
volatile int splitPointsCnt;
|
volatile int splitPointsCnt;
|
||||||
volatile bool is_searching;
|
volatile bool searching;
|
||||||
volatile bool do_exit;
|
volatile bool exit;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// MainThread and TimerThread are sublassed from Thread to charaterize the two
|
||||||
|
/// special threads: the main one and the recurring timer.
|
||||||
|
|
||||||
|
struct MainThread : public Thread {
|
||||||
|
MainThread() : thinking(true) {} // Avoid a race with start_thinking()
|
||||||
|
virtual void idle_loop();
|
||||||
|
volatile bool thinking;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TimerThread : public Thread {
|
struct TimerThread : public Thread {
|
||||||
|
@ -124,12 +133,6 @@ struct TimerThread : public Thread {
|
||||||
int msec;
|
int msec;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MainThread : public Thread {
|
|
||||||
MainThread() : is_finished(false) {} // Avoid a race with start_searching()
|
|
||||||
virtual void idle_loop();
|
|
||||||
volatile bool is_finished;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/// ThreadPool class handles all the threads related stuff like init, starting,
|
/// ThreadPool class handles all the threads related stuff like init, starting,
|
||||||
/// parking and, the most important, launching a slave thread at a split point.
|
/// parking and, the most important, launching a slave thread at a split point.
|
||||||
|
@ -142,22 +145,25 @@ public:
|
||||||
void exit(); // be initialized and valid during the whole thread lifetime.
|
void exit(); // be initialized and valid during the whole thread lifetime.
|
||||||
|
|
||||||
Thread& operator[](size_t id) { return *threads[id]; }
|
Thread& operator[](size_t id) { return *threads[id]; }
|
||||||
int min_split_depth() const { return minimumSplitDepth; }
|
|
||||||
size_t size() const { return threads.size(); }
|
size_t size() const { return threads.size(); }
|
||||||
MainThread* main_thread() { return static_cast<MainThread*>(threads[0]); }
|
MainThread* main_thread() { return static_cast<MainThread*>(threads[0]); }
|
||||||
TimerThread* timer_thread() { return timer; }
|
TimerThread* timer_thread() { return timer; }
|
||||||
|
|
||||||
void read_uci_options();
|
void read_uci_options();
|
||||||
bool available_slave_exists(Thread* master) const;
|
bool available_slave_exists(Thread* master) const;
|
||||||
void wait_for_search_finished();
|
void wait_for_think_finished();
|
||||||
void start_searching(const Position&, const Search::LimitsType&,
|
void start_thinking(const Position&, const Search::LimitsType&,
|
||||||
const std::vector<Move>&, Search::StateStackPtr&);
|
const std::vector<Move>&, Search::StateStackPtr&);
|
||||||
|
|
||||||
template <bool Fake>
|
template <bool Fake>
|
||||||
Value split(Position& pos, Search::Stack* ss, Value alpha, Value beta, Value bestValue, Move* bestMove,
|
Value split(Position& pos, Search::Stack* ss, Value alpha, Value beta, Value bestValue, Move* bestMove,
|
||||||
Depth depth, Move threatMove, int moveCount, MovePicker& mp, int nodeType);
|
Depth depth, Move threatMove, int moveCount, MovePicker& mp, int nodeType);
|
||||||
|
|
||||||
|
bool sleepWhileIdle;
|
||||||
|
Depth minimumSplitDepth;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class Thread;
|
friend struct Thread;
|
||||||
friend struct MainThread;
|
friend struct MainThread;
|
||||||
friend void check_time();
|
friend void check_time();
|
||||||
|
|
||||||
|
@ -165,10 +171,7 @@ private:
|
||||||
TimerThread* timer;
|
TimerThread* timer;
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
ConditionVariable sleepCondition;
|
ConditionVariable sleepCondition;
|
||||||
Depth minimumSplitDepth;
|
|
||||||
int maxThreadsPerSplitPoint;
|
int maxThreadsPerSplitPoint;
|
||||||
public:
|
|
||||||
bool sleepWhileIdle;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ThreadPool Threads;
|
extern ThreadPool Threads;
|
||||||
|
|
|
@ -113,7 +113,7 @@ void UCI::loop(const string& args) {
|
||||||
|
|
||||||
} while (token != "quit" && args.empty()); // Args have one-shot behaviour
|
} while (token != "quit" && args.empty()); // Args have one-shot behaviour
|
||||||
|
|
||||||
Threads.wait_for_search_finished(); // Cannot quit while search is running
|
Threads.wait_for_think_finished(); // Cannot quit while search is running
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -207,6 +207,6 @@ namespace {
|
||||||
else if (token == "ponder") limits.ponder = true;
|
else if (token == "ponder") limits.ponder = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Threads.start_searching(pos, limits, searchMoves, SetupStates);
|
Threads.start_thinking(pos, limits, searchMoves, SetupStates);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue