int active_threads() const { return ActiveThreads; }
void set_active_threads(int newActiveThreads) { ActiveThreads = newActiveThreads; }
- void set_stop_request(int threadID) { threads[threadID].stopRequest = true; }
void incrementNodeCounter(int threadID) { threads[threadID].nodes++; }
void incrementBetaCounter(Color us, Depth d, int threadID) { threads[threadID].betaCutOffs[us] += unsigned(d); }
void print_current_line(SearchStack ss[], int ply, int threadID);
void wake_sleeping_threads();
void put_threads_to_sleep();
void idle_loop(int threadID, SplitPoint* waitSp);
- bool split(const Position& pos, SearchStack* ss, int ply, Value* alpha, Value* beta, Value* bestValue,
+ bool split(const Position& pos, SearchStack* ss, int ply, Value* alpha, const Value beta, Value* bestValue,
const Value futilityValue, Depth depth, int* moves, MovePicker* mp, int master, bool pvNode);
private:
&& TM.available_thread_exists(threadID)
&& !AbortSearch
&& !TM.thread_should_stop(threadID)
- && TM.split(pos, ss, ply, &alpha, &beta, &bestValue, VALUE_NONE,
+ && TM.split(pos, ss, ply, &alpha, beta, &bestValue, VALUE_NONE,
depth, &moveCount, &mp, threadID, true))
break;
}
&& TM.available_thread_exists(threadID)
&& !AbortSearch
&& !TM.thread_should_stop(threadID)
- && TM.split(pos, ss, ply, &beta, &beta, &bestValue, futilityValue, //FIXME: SMP & futilityValue
+ && TM.split(pos, ss, ply, NULL, beta, &bestValue, futilityValue, //FIXME: SMP & futilityValue
depth, &moveCount, &mp, threadID, false))
break;
}
assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
- if (TM.thread_should_stop(threadID))
- {
- lock_grab(&(sp->lock));
- break;
- }
-
// New best move?
if (value > sp->bestValue) // Less then 2% of cases
{
sp->bestValue = value;
if (sp->bestValue >= sp->beta)
{
+ sp->stopRequest = true;
sp_update_pv(sp->parentSstack, ss, sp->ply);
- for (int i = 0; i < TM.active_threads(); i++)
- if (i != threadID && (i == sp->master || sp->slaves[i]))
- TM.set_stop_request(i);
-
- sp->finished = true;
}
}
lock_release(&(sp->lock));
/* Here we have the lock still grabbed */
- // If this is the master thread and we have been asked to stop because of
- // a beta cutoff higher up in the tree, stop all slave threads. Note that
- // thread_should_stop(threadID) does not imply that 'stop' flag is set, so
- // do this explicitly now, under lock protection.
- if (sp->master == threadID && TM.thread_should_stop(threadID))
- for (int i = 0; i < TM.active_threads(); i++)
- if (sp->slaves[i] || i == threadID)
- TM.set_stop_request(i);
-
sp->cpus--;
sp->slaves[threadID] = 0;
assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
- if (TM.thread_should_stop(threadID))
- {
- lock_grab(&(sp->lock));
- break;
- }
-
// New best move?
if (value > sp->bestValue) // Less then 2% of cases
{
{
// Ask threads to stop before to modify sp->alpha
if (value >= sp->beta)
- {
- for (int i = 0; i < TM.active_threads(); i++)
- if (i != threadID && (i == sp->master || sp->slaves[i]))
- TM.set_stop_request(i);
-
- sp->finished = true;
- }
+ sp->stopRequest = true;
sp->alpha = value;
/* Here we have the lock still grabbed */
- // If this is the master thread and we have been asked to stop because of
- // a beta cutoff higher up in the tree, stop all slave threads. Note that
- // thread_should_stop(threadID) does not imply that 'stop' flag is set, so
- // do this explicitly now, under lock protection.
- if (sp->master == threadID && TM.thread_should_stop(threadID))
- for (int i = 0; i < TM.active_threads(); i++)
- if (sp->slaves[i] || i == threadID)
- TM.set_stop_request(i);
-
sp->cpus--;
sp->slaves[threadID] = 0;
// If this thread has been assigned work, launch a search
if (threads[threadID].state == THREAD_WORKISWAITING)
{
+ assert(!AllThreadsShouldExit);
+
threads[threadID].state = THREAD_SEARCHING;
if (threads[threadID].splitPoint->pvNode)
assert(threads[threadID].state == THREAD_SEARCHING);
- // If this is a slave thread reset to available, instead
- // if it is a master thread and all slaves have finished
- // then leave as is to avoid booking by another master,
- // we will leave idle loop shortly anyhow.
- if ( !AllThreadsShouldExit
- && (!waitSp || waitSp->cpus > 0))
- threads[threadID].state = THREAD_AVAILABLE;
+ threads[threadID].state = THREAD_AVAILABLE;
}
// If this thread is the master of a split point and all threads have
lock_init(&IOLock, NULL);
// Initialize SplitPointStack locks
- for (int i = 0; i < MAX_THREADS; i++)
+ for (i = 0; i < MAX_THREADS; i++)
for (int j = 0; j < ACTIVE_SPLIT_POINTS_MAX; j++)
{
SplitPointStack[i][j].parent = NULL;
// Wait for thread termination
for (int i = 1; i < MAX_THREADS; i++)
- while (threads[i].state != THREAD_TERMINATED)
- threads[i].stopRequest = true;
+ while (threads[i].state != THREAD_TERMINATED);
// Now we can safely destroy the locks
for (int i = 0; i < MAX_THREADS; i++)
}
- // thread_should_stop() checks whether the thread with a given threadID has
- // been asked to stop, directly or indirectly. This can happen if a beta
- // cutoff has occurred in the thread's currently active split point, or in
- // some ancestor of the current split point.
+ // thread_should_stop() checks whether the thread should stop its search.
+ // This can happen if a beta cutoff has occurred in the thread's currently
+ // active split point, or in some ancestor of the current split point.
bool ThreadsManager::thread_should_stop(int threadID) const {
SplitPoint* sp;
- if (threads[threadID].stopRequest)
- return true;
-
- if (ActiveThreads <= 2)
- return false;
-
- for (sp = threads[threadID].splitPoint; sp != NULL; sp = sp->parent)
- if (sp->finished)
- return true;
-
- return false;
+ for (sp = threads[threadID].splitPoint; sp && !sp->stopRequest; sp = sp->parent);
+ return sp != NULL;
}
// splitPoint->cpus becomes 0), split() returns true.
bool ThreadsManager::split(const Position& p, SearchStack* sstck, int ply,
- Value* alpha, Value* beta, Value* bestValue, const Value futilityValue,
+ Value* alpha, const Value beta, Value* bestValue, const Value futilityValue,
Depth depth, int* moves, MovePicker* mp, int master, bool pvNode) {
assert(p.is_ok());
}
// Pick the next available split point object from the split point stack
- splitPoint = SplitPointStack[master] + threads[master].activeSplitPoints;
- threads[master].activeSplitPoints++;
+ splitPoint = &SplitPointStack[master][threads[master].activeSplitPoints];
// Initialize the split point object
splitPoint->parent = threads[master].splitPoint;
- splitPoint->finished = false;
+ splitPoint->stopRequest = false;
splitPoint->ply = ply;
splitPoint->depth = depth;
- splitPoint->alpha = pvNode ? *alpha : (*beta - 1);
- splitPoint->beta = *beta;
+ splitPoint->alpha = pvNode ? *alpha : beta - 1;
+ splitPoint->beta = beta;
splitPoint->pvNode = pvNode;
splitPoint->bestValue = *bestValue;
splitPoint->futilityValue = futilityValue;
splitPoint->slaves[i] = 0;
threads[master].splitPoint = splitPoint;
+ threads[master].activeSplitPoints++;
// If we are here it means we are not available
assert(threads[master].state != THREAD_AVAILABLE);
if (thread_is_available(i, master))
{
threads[i].state = THREAD_BOOKED;
- threads[i].stopRequest = false;
threads[i].splitPoint = splitPoint;
splitPoint->slaves[i] = 1;
splitPoint->cpus++;
if (pvNode)
*alpha = splitPoint->alpha;
- *beta = splitPoint->beta;
*bestValue = splitPoint->bestValue;
- threads[master].stopRequest = false;
threads[master].activeSplitPoints--;
threads[master].splitPoint = splitPoint->parent;
{
while (threads[i].state != THREAD_SLEEPING);
- // These two flags can be in a random state
- threads[i].stopRequest = threads[i].printCurrentLineRequest = false;
+ // This flag can be in a random state
+ threads[i].printCurrentLineRequest = false;
}
}