int ActiveThreads;
volatile bool AllThreadsShouldExit;
Thread threads[MAX_THREADS];
- Lock MPLock;
- WaitCondition WaitCond[MAX_THREADS];
+ Lock MPLock, SleepLock[MAX_THREADS];
+ WaitCondition SleepCond[MAX_THREADS];
};
// Multi-threads related variables
Depth MinimumSplitDepth;
int MaxThreadsPerSplitPoint;
- bool UseSleepingMaster;
+ bool UseSleepingThreads;
ThreadsManager ThreadsMgr;
// Node counters, used only by thread[0] but try to keep in different cache
// Init reductions array
for (hd = 1; hd < 64; hd++) for (mc = 1; mc < 64; mc++)
{
- double pvRed = 0.33 + log(double(hd)) * log(double(mc)) / 4.5;
+ double pvRed = log(double(hd)) * log(double(mc)) / 3.0;
double nonPVRed = 0.33 + log(double(hd)) * log(double(mc)) / 2.25;
ReductionMatrix[PV][hd][mc] = (int8_t) ( pvRed >= 1.0 ? floor( pvRed * int(ONE_PLY)) : 0);
ReductionMatrix[NonPV][hd][mc] = (int8_t) (nonPVRed >= 1.0 ? floor(nonPVRed * int(ONE_PLY)) : 0);
MaxThreadsPerSplitPoint = Options["Maximum Number of Threads per Split Point"].value<int>();
MultiPV = Options["MultiPV"].value<int>();
UseLogFile = Options["Use Search Log"].value<bool>();
- UseSleepingMaster = Options["Use Sleeping Master"].value<bool>();
+ UseSleepingThreads = Options["Use Sleeping Threads"].value<bool>();
if (UseLogFile)
LogFile.open(Options["Search Log Filename"].value<std::string>().c_str(), std::ios::out | std::ios::app);
if (newActiveThreads != ThreadsMgr.active_threads())
{
ThreadsMgr.set_active_threads(newActiveThreads);
- init_eval(ThreadsMgr.active_threads());
+ init_eval(newActiveThreads);
}
+ // Wake up needed threads
+ for (int i = 1; i < newActiveThreads; i++)
+ ThreadsMgr.wake_sleeping_thread(i);
+
// Set thinking time
int myTime = time[pos.side_to_move()];
int myIncrement = increment[pos.side_to_move()];
if (UseLogFile)
LogFile.close();
+ // This makes all the threads to go to sleep
+ ThreadsMgr.set_active_threads(1);
+
return !Quit;
}
<< " time " << current_search_time() << endl;
// Print the best move and the ponder move to the standard output
- if (pv[0] == MOVE_NONE)
+ if (pv[0] == MOVE_NONE || MultiPV > 1)
{
pv[0] = rml.move(0);
pv[1] = MOVE_NONE;
&& !isCheck
&& refinedValue < beta - razor_margin(depth)
&& ttMove == MOVE_NONE
- && (ss-1)->currentMove != MOVE_NULL
&& !value_is_mate(beta)
&& !pos.has_pawn_on_7th(pos.side_to_move()))
{
continue;
}
+
+ // Prune neg. see moves at low depths
+ if ( predictedDepth < 2 * ONE_PLY
+ && bestValue > value_mated_in(PLY_MAX)
+ && pos.see_sign(move) < 0)
+ {
+ if (SpNode)
+ lock_grab(&(sp->lock));
+
+ continue;
+ }
}
// Step 13. Make the move
// 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
- || (threads[threadID].state == THREAD_AVAILABLE && (!sp || UseSleepingMaster)))
+ while ( threadID >= ActiveThreads || threads[threadID].state == THREAD_INITIALIZING
+ || (UseSleepingThreads && threads[threadID].state == THREAD_AVAILABLE))
{
- lock_grab(&MPLock);
+ 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()
+ lock_grab(&SleepLock[threadID]);
- // Test with lock held to avoid races with wake_sleeping_thread()
+ // 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);
- // Retest sleep conditions under lock protection
- if ( AllThreadsShouldExit
- || allFinished
- || !( threadID >= ActiveThreads
- || threads[threadID].state == THREAD_INITIALIZING
- || (threads[threadID].state == THREAD_AVAILABLE && (!sp || UseSleepingMaster))))
+ if (allFinished || AllThreadsShouldExit)
{
- lock_release(&MPLock);
+ lock_release(&SleepLock[threadID]);
break;
}
- // Put thread to sleep
- threads[threadID].state = THREAD_AVAILABLE;
- cond_wait(&WaitCond[threadID], &MPLock);
- lock_release(&MPLock);
+ // Do sleep here after retesting sleep conditions
+ if (threadID >= ActiveThreads || threads[threadID].state == THREAD_AVAILABLE)
+ cond_wait(&SleepCond[threadID], &SleepLock[threadID]);
+
+ lock_release(&SleepLock[threadID]);
}
// If this thread has been assigned work, launch a search
if (tsp->pvNode)
search<PV, true>(pos, ss, tsp->alpha, tsp->beta, tsp->depth, tsp->ply);
- else {
+ else
search<NonPV, true>(pos, ss, tsp->alpha, tsp->beta, tsp->depth, tsp->ply);
- }
+
assert(threads[threadID].state == THREAD_SEARCHING);
threads[threadID].state = THREAD_AVAILABLE;
// 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 (UseSleepingMaster && 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);
}
lock_init(&MPLock);
for (i = 0; i < MAX_THREADS; i++)
- cond_init(&WaitCond[i]);
+ {
+ lock_init(&SleepLock[i]);
+ cond_init(&SleepCond[i]);
+ }
// Initialize splitPoints[] locks
for (i = 0; i < MAX_THREADS; i++)
if (!ok)
{
cout << "Failed to create thread number " << i << endl;
- Application::exit_with_failure();
+ exit(EXIT_FAILURE);
}
// Wait until the thread has finished launching and is gone to sleep
// Now we can safely destroy the wait conditions
for (int i = 0; i < MAX_THREADS; i++)
- cond_destroy(&WaitCond[i]);
+ {
+ lock_destroy(&SleepLock[i]);
+ cond_destroy(&SleepCond[i]);
+ }
}
assert(i == master || threads[i].state == THREAD_BOOKED);
threads[i].state = THREAD_WORKISWAITING; // This makes the slave to exit from idle_loop()
- if (i != master)
+
+ if (UseSleepingThreads && i != master)
wake_sleeping_thread(i);
}
}
- // wake_sleeping_thread() wakes up all sleeping threads when it is time
- // to start a new search from the root.
+ // wake_sleeping_thread() wakes up the thread with the given threadID
+ // when it is time to start a new search.
void ThreadsManager::wake_sleeping_thread(int threadID) {
- lock_grab(&MPLock);
- cond_signal(&WaitCond[threadID]);
- lock_release(&MPLock);
+ lock_grab(&SleepLock[threadID]);
+ cond_signal(&SleepCond[threadID]);
+ lock_release(&SleepLock[threadID]);
}