Also rename ThreadsManager memeber data to be lower case.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
void init_threads();
void exit_threads();
void init_threads();
void exit_threads();
- int active_threads() const { return ActiveThreads; }
- void set_active_threads(int newActiveThreads) { ActiveThreads = newActiveThreads; }
+ int min_split_depth() const { return minimumSplitDepth; }
+ int active_threads() const { return activeThreads; }
+ void set_active_threads(int cnt) { activeThreads = cnt; }
+ void read_uci_options();
bool available_thread_exists(int master) const;
bool thread_is_available(int slave, int master) const;
bool thread_should_stop(int threadID) const;
bool available_thread_exists(int master) const;
bool thread_is_available(int slave, int master) const;
bool thread_should_stop(int threadID) const;
Depth depth, Move threatMove, bool mateThreat, int moveCount, MovePicker* mp, bool pvNode);
private:
Depth depth, Move threatMove, bool mateThreat, int moveCount, MovePicker* mp, bool pvNode);
private:
- int ActiveThreads;
- volatile bool AllThreadsShouldExit;
+ Depth minimumSplitDepth;
+ int maxThreadsPerSplitPoint;
+ bool useSleepingThreads;
+ int activeThreads;
+ volatile bool allThreadsShouldExit;
Thread threads[MAX_THREADS];
Thread threads[MAX_THREADS];
- Lock MPLock, SleepLock[MAX_THREADS];
- WaitCondition SleepCond[MAX_THREADS];
+ Lock mpLock, sleepLock[MAX_THREADS];
+ WaitCondition sleepCond[MAX_THREADS];
bool UseLogFile;
std::ofstream LogFile;
bool UseLogFile;
std::ofstream LogFile;
- // Multi-threads related variables
- Depth MinimumSplitDepth;
- int MaxThreadsPerSplitPoint;
- bool UseSleepingThreads;
+ // Multi-threads manager object
ThreadsManager ThreadsMgr;
// Node counters, used only by thread[0] but try to keep in different cache
ThreadsManager ThreadsMgr;
// Node counters, used only by thread[0] but try to keep in different cache
PawnEndgameExtension[0] = Options["Pawn Endgame Extension (non-PV nodes)"].value<Depth>();
MateThreatExtension[1] = Options["Mate Threat Extension (PV nodes)"].value<Depth>();
MateThreatExtension[0] = Options["Mate Threat Extension (non-PV nodes)"].value<Depth>();
PawnEndgameExtension[0] = Options["Pawn Endgame Extension (non-PV nodes)"].value<Depth>();
MateThreatExtension[1] = Options["Mate Threat Extension (PV nodes)"].value<Depth>();
MateThreatExtension[0] = Options["Mate Threat Extension (non-PV nodes)"].value<Depth>();
-
- MinimumSplitDepth = Options["Minimum Split Depth"].value<int>() * ONE_PLY;
- MaxThreadsPerSplitPoint = Options["Maximum Number of Threads per Split Point"].value<int>();
- MultiPV = Options["MultiPV"].value<int>();
- UseLogFile = Options["Use Search Log"].value<bool>();
- UseSleepingThreads = Options["Use Sleeping Threads"].value<bool>();
+ MultiPV = Options["MultiPV"].value<int>();
+ UseLogFile = Options["Use Search Log"].value<bool>();
if (UseLogFile)
LogFile.open(Options["Search Log Filename"].value<std::string>().c_str(), std::ios::out | std::ios::app);
if (UseLogFile)
LogFile.open(Options["Search Log Filename"].value<std::string>().c_str(), std::ios::out | std::ios::app);
read_weights(pos.side_to_move());
// Set the number of active threads
read_weights(pos.side_to_move());
// Set the number of active threads
- int newActiveThreads = Options["Threads"].value<int>();
- if (newActiveThreads != ThreadsMgr.active_threads())
- {
- ThreadsMgr.set_active_threads(newActiveThreads);
- init_eval(newActiveThreads);
- }
+ ThreadsMgr.read_uci_options();
+ init_eval(ThreadsMgr.active_threads());
// Wake up needed threads
// Wake up needed threads
- for (int i = 1; i < newActiveThreads; i++)
+ for (int i = 1; i < ThreadsMgr.active_threads(); i++)
ThreadsMgr.wake_sleeping_thread(i);
// Set thinking time
ThreadsMgr.wake_sleeping_thread(i);
// Set thinking time
// Step 18. Check for split
if ( !SpNode
// Step 18. Check for split
if ( !SpNode
- && depth >= MinimumSplitDepth
+ && depth >= ThreadsMgr.min_split_depth()
&& ThreadsMgr.active_threads() > 1
&& bestValue < beta
&& ThreadsMgr.available_thread_exists(threadID)
&& ThreadsMgr.active_threads() > 1
&& bestValue < beta
&& ThreadsMgr.available_thread_exists(threadID)
/// The ThreadsManager class
/// The ThreadsManager class
+ // read_uci_options() updates number of active threads and other internal
+ // parameters according to the UCI options values. It is called before
+ // to start a new search.
+
+ void ThreadsManager::read_uci_options() {
+
+ maxThreadsPerSplitPoint = Options["Maximum Number of Threads per Split Point"].value<int>();
+ minimumSplitDepth = Options["Minimum Split Depth"].value<int>() * ONE_PLY;
+ useSleepingThreads = Options["Use Sleeping Threads"].value<bool>();
+ activeThreads = Options["Threads"].value<int>();
+ }
+
+
// idle_loop() is where the threads are parked when they have no work to do.
// The parameter 'sp', if non-NULL, is a pointer to an active SplitPoint
// object for which the current thread is the master.
// idle_loop() is where the threads are parked when they have no work to do.
// The parameter 'sp', if non-NULL, is a pointer to an active SplitPoint
// object for which the current thread is the master.
{
// Slave threads can exit as soon as AllThreadsShouldExit raises,
// master should exit as last one.
{
// Slave threads can exit as soon as AllThreadsShouldExit raises,
// master should exit as last one.
- if (AllThreadsShouldExit)
+ if (allThreadsShouldExit)
{
assert(!sp);
threads[threadID].state = THREAD_TERMINATED;
{
assert(!sp);
threads[threadID].state = THREAD_TERMINATED;
// If we are not thinking, wait for a condition to be signaled
// instead of wasting CPU time polling for work.
// If we are not thinking, wait for a condition to be signaled
// instead of wasting CPU time polling for work.
- while ( threadID >= ActiveThreads || threads[threadID].state == THREAD_INITIALIZING
- || (UseSleepingThreads && threads[threadID].state == THREAD_AVAILABLE))
+ while ( threadID >= activeThreads || threads[threadID].state == THREAD_INITIALIZING
+ || (useSleepingThreads && threads[threadID].state == THREAD_AVAILABLE))
- assert(!sp || UseSleepingThreads);
- assert(threadID != 0 || UseSleepingThreads);
+ assert(!sp || useSleepingThreads);
+ assert(threadID != 0 || useSleepingThreads);
if (threads[threadID].state == THREAD_INITIALIZING)
threads[threadID].state = THREAD_AVAILABLE;
// Grab the lock to avoid races with wake_sleeping_thread()
if (threads[threadID].state == THREAD_INITIALIZING)
threads[threadID].state = THREAD_AVAILABLE;
// Grab the lock to avoid races with wake_sleeping_thread()
- lock_grab(&SleepLock[threadID]);
+ lock_grab(&sleepLock[threadID]);
// If we are master and all slaves have finished do not go to sleep
// If we are master and all slaves have finished do not go to sleep
- for (i = 0; sp && i < ActiveThreads && !sp->slaves[i]; i++) {}
- allFinished = (i == ActiveThreads);
+ for (i = 0; sp && i < activeThreads && !sp->slaves[i]; i++) {}
+ allFinished = (i == activeThreads);
- if (allFinished || AllThreadsShouldExit)
+ if (allFinished || allThreadsShouldExit)
- lock_release(&SleepLock[threadID]);
+ lock_release(&sleepLock[threadID]);
break;
}
// Do sleep here after retesting sleep conditions
break;
}
// Do sleep here after retesting sleep conditions
- if (threadID >= ActiveThreads || threads[threadID].state == THREAD_AVAILABLE)
- cond_wait(&SleepCond[threadID], &SleepLock[threadID]);
+ if (threadID >= activeThreads || threads[threadID].state == THREAD_AVAILABLE)
+ cond_wait(&sleepCond[threadID], &sleepLock[threadID]);
- lock_release(&SleepLock[threadID]);
+ lock_release(&sleepLock[threadID]);
}
// If this thread has been assigned work, launch a search
if (threads[threadID].state == THREAD_WORKISWAITING)
{
}
// If this thread has been assigned work, launch a search
if (threads[threadID].state == THREAD_WORKISWAITING)
{
- assert(!AllThreadsShouldExit);
+ assert(!allThreadsShouldExit);
threads[threadID].state = THREAD_SEARCHING;
threads[threadID].state = THREAD_SEARCHING;
// Wake up master thread so to allow it to return from the idle loop in
// case we are the last slave of the split point.
// Wake up master thread so to allow it to return from the idle loop in
// case we are the last slave of the split point.
- if (UseSleepingThreads && threadID != tsp->master && threads[tsp->master].state == THREAD_AVAILABLE)
+ if (useSleepingThreads && threadID != tsp->master && threads[tsp->master].state == THREAD_AVAILABLE)
wake_sleeping_thread(tsp->master);
}
// 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.
wake_sleeping_thread(tsp->master);
}
// 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.
- for (i = 0; sp && i < ActiveThreads && !sp->slaves[i]; i++) {}
- allFinished = (i == ActiveThreads);
+ for (i = 0; sp && i < activeThreads && !sp->slaves[i]; i++) {}
+ allFinished = (i == activeThreads);
bool ok;
// Initialize global locks
bool ok;
// Initialize global locks
for (i = 0; i < MAX_THREADS; i++)
{
for (i = 0; i < MAX_THREADS; i++)
{
- lock_init(&SleepLock[i]);
- cond_init(&SleepCond[i]);
+ lock_init(&sleepLock[i]);
+ cond_init(&sleepCond[i]);
}
// Initialize splitPoints[] locks
}
// Initialize splitPoints[] locks
lock_init(&(threads[i].splitPoints[j].lock));
// Will be set just before program exits to properly end the threads
lock_init(&(threads[i].splitPoints[j].lock));
// Will be set just before program exits to properly end the threads
- AllThreadsShouldExit = false;
+ allThreadsShouldExit = false;
// Threads will be put all threads to sleep as soon as created
// Threads will be put all threads to sleep as soon as created
// All threads except the main thread should be initialized to THREAD_INITIALIZING
threads[0].state = THREAD_SEARCHING;
// All threads except the main thread should be initialized to THREAD_INITIALIZING
threads[0].state = THREAD_SEARCHING;
void ThreadsManager::exit_threads() {
void ThreadsManager::exit_threads() {
- AllThreadsShouldExit = true; // Let the woken up threads to exit idle_loop()
+ allThreadsShouldExit = true; // Let the woken up threads to exit idle_loop()
// Wake up all the threads and waits for termination
for (int i = 1; i < MAX_THREADS; i++)
// Wake up all the threads and waits for termination
for (int i = 1; i < MAX_THREADS; i++)
for (int j = 0; j < MAX_ACTIVE_SPLIT_POINTS; j++)
lock_destroy(&(threads[i].splitPoints[j].lock));
for (int j = 0; j < MAX_ACTIVE_SPLIT_POINTS; j++)
lock_destroy(&(threads[i].splitPoints[j].lock));
// Now we can safely destroy the wait conditions
for (int i = 0; i < MAX_THREADS; i++)
{
// Now we can safely destroy the wait conditions
for (int i = 0; i < MAX_THREADS; i++)
{
- lock_destroy(&SleepLock[i]);
- cond_destroy(&SleepCond[i]);
+ lock_destroy(&sleepLock[i]);
+ cond_destroy(&sleepCond[i]);
bool ThreadsManager::thread_should_stop(int threadID) const {
bool ThreadsManager::thread_should_stop(int threadID) const {
- assert(threadID >= 0 && threadID < ActiveThreads);
+ assert(threadID >= 0 && threadID < activeThreads);
SplitPoint* sp = threads[threadID].splitPoint;
SplitPoint* sp = threads[threadID].splitPoint;
bool ThreadsManager::thread_is_available(int slave, int master) const {
bool ThreadsManager::thread_is_available(int slave, int master) const {
- assert(slave >= 0 && slave < ActiveThreads);
- assert(master >= 0 && master < ActiveThreads);
- assert(ActiveThreads > 1);
+ assert(slave >= 0 && slave < activeThreads);
+ assert(master >= 0 && master < activeThreads);
+ assert(activeThreads > 1);
if (threads[slave].state != THREAD_AVAILABLE || slave == master)
return false;
if (threads[slave].state != THREAD_AVAILABLE || slave == master)
return false;
// No active split points means that the thread is available as
// a slave for any other thread.
// No active split points means that the thread is available as
// a slave for any other thread.
- if (localActiveSplitPoints == 0 || ActiveThreads == 2)
+ if (localActiveSplitPoints == 0 || activeThreads == 2)
return true;
// Apply the "helpful master" concept if possible. Use localActiveSplitPoints
return true;
// Apply the "helpful master" concept if possible. Use localActiveSplitPoints
bool ThreadsManager::available_thread_exists(int master) const {
bool ThreadsManager::available_thread_exists(int master) const {
- assert(master >= 0 && master < ActiveThreads);
- assert(ActiveThreads > 1);
+ assert(master >= 0 && master < activeThreads);
+ assert(activeThreads > 1);
- for (int i = 0; i < ActiveThreads; i++)
+ for (int i = 0; i < activeThreads; i++)
if (thread_is_available(i, master))
return true;
if (thread_is_available(i, master))
return true;
assert(*alpha < beta);
assert(beta <= VALUE_INFINITE);
assert(depth > DEPTH_ZERO);
assert(*alpha < beta);
assert(beta <= VALUE_INFINITE);
assert(depth > DEPTH_ZERO);
- assert(pos.thread() >= 0 && pos.thread() < ActiveThreads);
- assert(ActiveThreads > 1);
+ assert(pos.thread() >= 0 && pos.thread() < activeThreads);
+ assert(activeThreads > 1);
int i, master = pos.thread();
Thread& masterThread = threads[master];
int i, master = pos.thread();
Thread& masterThread = threads[master];
// If no other thread is available to help us, or if we have too many
// active split points, don't split.
if ( !available_thread_exists(master)
|| masterThread.activeSplitPoints >= MAX_ACTIVE_SPLIT_POINTS)
{
// If no other thread is available to help us, or if we have too many
// active split points, don't split.
if ( !available_thread_exists(master)
|| masterThread.activeSplitPoints >= MAX_ACTIVE_SPLIT_POINTS)
{
splitPoint.pos = &pos;
splitPoint.nodes = 0;
splitPoint.parentSstack = ss;
splitPoint.pos = &pos;
splitPoint.nodes = 0;
splitPoint.parentSstack = ss;
- for (i = 0; i < ActiveThreads; i++)
+ for (i = 0; i < activeThreads; i++)
splitPoint.slaves[i] = 0;
masterThread.splitPoint = &splitPoint;
splitPoint.slaves[i] = 0;
masterThread.splitPoint = &splitPoint;
int workersCnt = 1; // At least the master is included
// Allocate available threads setting state to THREAD_BOOKED
int workersCnt = 1; // At least the master is included
// Allocate available threads setting state to THREAD_BOOKED
- for (i = 0; !Fake && i < ActiveThreads && workersCnt < MaxThreadsPerSplitPoint; i++)
+ for (i = 0; !Fake && i < activeThreads && workersCnt < maxThreadsPerSplitPoint; i++)
if (thread_is_available(i, master))
{
threads[i].state = THREAD_BOOKED;
if (thread_is_available(i, master))
{
threads[i].state = THREAD_BOOKED;
assert(Fake || workersCnt > 1);
// We can release the lock because slave threads are already booked and master is not available
assert(Fake || workersCnt > 1);
// We can release the lock because slave threads are already booked and master is not available
// Tell the threads that they have work to do. This will make them leave
// their idle loop. But before copy search stack tail for each thread.
// Tell the threads that they have work to do. This will make them leave
// their idle loop. But before copy search stack tail for each thread.
- for (i = 0; i < ActiveThreads; i++)
+ for (i = 0; i < activeThreads; i++)
if (i == master || splitPoint.slaves[i])
{
memcpy(splitPoint.sstack[i], ss - 1, 4 * sizeof(SearchStack));
if (i == master || splitPoint.slaves[i])
{
memcpy(splitPoint.sstack[i], ss - 1, 4 * sizeof(SearchStack));
threads[i].state = THREAD_WORKISWAITING; // This makes the slave to exit from idle_loop()
threads[i].state = THREAD_WORKISWAITING; // This makes the slave to exit from idle_loop()
- if (UseSleepingThreads && i != master)
+ if (useSleepingThreads && i != master)
wake_sleeping_thread(i);
}
wake_sleeping_thread(i);
}
// We have returned from the idle loop, which means that all threads are
// finished. Update alpha and bestValue, and return.
// We have returned from the idle loop, which means that all threads are
// finished. Update alpha and bestValue, and return.
*alpha = splitPoint.alpha;
*bestValue = splitPoint.bestValue;
*alpha = splitPoint.alpha;
*bestValue = splitPoint.bestValue;
masterThread.splitPoint = splitPoint.parent;
pos.set_nodes_searched(pos.nodes_searched() + splitPoint.nodes);
masterThread.splitPoint = splitPoint.parent;
pos.set_nodes_searched(pos.nodes_searched() + splitPoint.nodes);
void ThreadsManager::wake_sleeping_thread(int threadID) {
void ThreadsManager::wake_sleeping_thread(int threadID) {
- lock_grab(&SleepLock[threadID]);
- cond_signal(&SleepCond[threadID]);
- lock_release(&SleepLock[threadID]);
+ lock_grab(&sleepLock[threadID]);
+ cond_signal(&sleepCond[threadID]);
+ lock_release(&sleepLock[threadID]);