Allow a slave to 'late join' another splitpoint

Instead of waiting to be allocated, actively search
for another split point to join when finishes its
search. Also modify split conditions.

This patch has been tested with 7 threads SMP and
passed both STC:

LLR: 2.97 (-2.94,2.94) [-1.50,4.50]
Total: 2885 W: 519 L: 410 D: 1956

And a reduced-LTC at  25+0.05
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 4401 W: 684 L: 566 D: 3151

Was then retested against regression in 3 thread case
at standard LTC of  60+0.05:

LLR: 2.96 (-2.94,2.94) [-4.00,0.00]
Total: 40809 W: 5446 L: 5406 D: 29957

bench: 8802105
This commit is contained in:
Joona Kiiski
2014-05-03 18:29:31 +01:00
committed by Marco Costalba
parent 8f6a494ad7
commit f6e98a924a
3 changed files with 53 additions and 6 deletions

View File

@@ -984,8 +984,10 @@ moves_loop: // When in check and at SpNode search starts from here
// Step 19. Check for splitting the search
if ( !SpNode
&& Threads.size() >= 2
&& depth >= Threads.minimumSplitDepth
&& Threads.available_slave(thisThread)
&& ( !thisThread->activeSplitPoint
|| !thisThread->activeSplitPoint->allowLatejoin)
&& thisThread->splitPointsSize < MAX_SPLITPOINTS_PER_THREAD)
{
assert(bestValue > -VALUE_INFINITE && bestValue < beta);
@@ -1527,9 +1529,9 @@ void Thread::idle_loop() {
assert(searching);
searching = false;
activePosition = NULL;
sp->slavesMask.reset(idx);
sp->allowLatejoin = false;
sp->nodes += pos.nodes_searched();
// Wake up the master thread so to allow it to return from the idle
@@ -1547,6 +1549,10 @@ void Thread::idle_loop() {
// the sp master. Also accessing other Thread objects is unsafe because
// if we are exiting there is a chance that they are already freed.
sp->mutex.unlock();
// Try to late join to another splitpoint
if (Threads.size() <= 2 || !attempt_to_latejoin()) // FIXME: attempt_to_latejoin() is theoretically unsafe when were are exiting the program...
searching = false;
}
// If this thread is the master of a split point and all slaves have finished
@@ -1562,6 +1568,44 @@ void Thread::idle_loop() {
}
}
bool Thread::attempt_to_latejoin()
{
SplitPoint *sp;
size_t i;
bool success = false;
for (i = 0; i < Threads.size(); ++i)
{
int size = Threads[i]->splitPointsSize; // Make a local copy to prevent size from changing under our feet.
sp = size ? &Threads[i]->splitPoints[size - 1] : NULL;
if ( sp
&& sp->allowLatejoin
&& available_to(Threads[i], true))
break;
}
if (i == Threads.size())
return false; // No suitable splitpoint found!
// Recheck conditions under lock protection
Threads.mutex.lock();
sp->mutex.lock();
if ( sp->allowLatejoin
&& available_to(Threads[i], true))
{
activeSplitPoint = sp;
sp->slavesMask.set(this->idx);
success = true;
}
sp->mutex.unlock();
Threads.mutex.unlock();
return success;
}
/// check_time() is called by the timer thread when the timer triggers. It is
/// used to print debug info and, more importantly, to detect when we are out of