It is redundant with splitPoint->slaves[].
Also move slaves[MAX_THREADS] among the shared data in
SplitPoint definition as it should have been already.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
alpha = value;
update_pv(ss, ply);
alpha = value;
update_pv(ss, ply);
if (value == value_mate_in(ply + 1))
ss[ply].mateKiller = move;
}
if (value == value_mate_in(ply + 1))
ss[ply].mateKiller = move;
}
/* Here we have the lock still grabbed */
sp->slaves[threadID] = 0;
/* Here we have the lock still grabbed */
sp->slaves[threadID] = 0;
lock_release(&(sp->lock));
}
lock_release(&(sp->lock));
}
threads[threadID].state = THREAD_AVAILABLE;
}
threads[threadID].state = THREAD_AVAILABLE;
}
- // If this thread is the master of a split point and all threads 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.
- if (sp && sp->cpus == 0)
+ int i = 0;
+ for ( ; sp && !sp->slaves[i] && i < ActiveThreads; i++) {}
+
+ if (i == ActiveThreads)
- // Because sp->cpus is decremented under lock protection,
- // be sure sp->lock has been released before to proceed.
+ // Because sp->slaves[] is reset under lock protection,
+ // be sure sp->lock has been released before to return.
lock_grab(&(sp->lock));
lock_release(&(sp->lock));
lock_grab(&(sp->lock));
lock_release(&(sp->lock));
// data that must be copied to the helper threads (the current position and
// search stack, alpha, beta, the search depth, etc.), and we tell our
// helper threads that they have been assigned work. This will cause them
// data that must be copied to the helper threads (the current position and
// search stack, alpha, beta, the search depth, etc.), and we tell our
// helper threads that they have been assigned work. This will cause them
- // to instantly leave their idle loops and call sp_search_pv(). When all
- // threads have returned from sp_search_pv (or, equivalently, when
- // splitPoint->cpus becomes 0), split() returns true.
+ // to instantly leave their idle loops and call sp_search(). When all
+ // threads have returned from sp_search() then split() returns true.
template <bool Fake>
bool ThreadsManager::split(const Position& p, SearchStack* sstck, int ply, Value* alpha,
template <bool Fake>
bool ThreadsManager::split(const Position& p, SearchStack* sstck, int ply, Value* alpha,
splitPoint->master = master;
splitPoint->mp = mp;
splitPoint->moves = *moves;
splitPoint->master = master;
splitPoint->mp = mp;
splitPoint->moves = *moves;
splitPoint->pos = &p;
splitPoint->parentSstack = sstck;
for (int i = 0; i < ActiveThreads; i++)
splitPoint->pos = &p;
splitPoint->parentSstack = sstck;
for (int i = 0; i < ActiveThreads; i++)
// If we are here it means we are not available
assert(threads[master].state != THREAD_AVAILABLE);
// If we are here it means we are not available
assert(threads[master].state != THREAD_AVAILABLE);
+ int workersCnt = 1; // At least the master is included
+
// Allocate available threads setting state to THREAD_BOOKED
// Allocate available threads setting state to THREAD_BOOKED
- for (int i = 0; !Fake && i < ActiveThreads && splitPoint->cpus < MaxThreadsPerSplitPoint; i++)
+ for (int i = 0; !Fake && i < ActiveThreads && workersCnt < MaxThreadsPerSplitPoint; i++)
if (thread_is_available(i, master))
{
threads[i].state = THREAD_BOOKED;
threads[i].splitPoint = splitPoint;
splitPoint->slaves[i] = 1;
if (thread_is_available(i, master))
{
threads[i].state = THREAD_BOOKED;
threads[i].splitPoint = splitPoint;
splitPoint->slaves[i] = 1;
- assert(Fake || splitPoint->cpus > 1);
+ assert(Fake || workersCnt > 1);
// We can release the lock because slave threads are already booked and master is not available
lock_release(&MPLock);
// We can release the lock because slave threads are already booked and master is not available
lock_release(&MPLock);
// which it will instantly launch a search, because its state is
// THREAD_WORKISWAITING. We send the split point as a second parameter to the
// idle loop, which means that the main thread will return from the idle
// which it will instantly launch a search, because its state is
// THREAD_WORKISWAITING. We send the split point as a second parameter to the
// idle loop, which means that the main thread will return from the idle
- // loop when all threads have finished their work at this split point
- // (i.e. when splitPoint->cpus == 0).
+ // loop when all threads have finished their work at this split point.
idle_loop(master, splitPoint);
// We have returned from the idle loop, which means that all threads are
idle_loop(master, splitPoint);
// We have returned from the idle loop, which means that all threads are
Depth depth;
bool pvNode, mateThreat;
Value beta;
Depth depth;
bool pvNode, mateThreat;
Value beta;
- int ply, master, slaves[MAX_THREADS];
SearchStack sstack[MAX_THREADS][PLY_MAX_PLUS_2];
// Const pointers to shared data
SearchStack sstack[MAX_THREADS][PLY_MAX_PLUS_2];
// Const pointers to shared data
volatile Value alpha;
volatile Value bestValue;
volatile int moves;
volatile Value alpha;
volatile Value bestValue;
volatile int moves;
volatile bool stopRequest;
volatile bool stopRequest;
+ volatile int slaves[MAX_THREADS];
};
// ThreadState type is used to represent thread's current state
};
// ThreadState type is used to represent thread's current state