X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fthread.cpp;h=9e96be6eb7fa326d79b91761fe1aae73e232af8d;hp=eb991f65abdead61f07403a70de375913a5a478d;hb=1e032ece92da0085000cfdde28cab05029dedce3;hpb=f5727deee3823accf791984836f45db78e3a53e5 diff --git a/src/thread.cpp b/src/thread.cpp index eb991f65..9e96be6e 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -1,7 +1,7 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Copyright (C) 2004-2008 Tord Romstad (Glaurung author) - Copyright (C) 2008-2013 Marco Costalba, Joona Kiiski, Tord Romstad + Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,6 +29,8 @@ using namespace Search; ThreadPool Threads; // Global object +extern void check_time(); + namespace { // start_routine() is the C function which is called when a new thread @@ -57,7 +59,7 @@ namespace { } -// ThreadBase::notify_one() wakes up the thread when there is some work to do +// notify_one() wakes up the thread when there is some work to do void ThreadBase::notify_one() { @@ -67,7 +69,7 @@ void ThreadBase::notify_one() { } -// ThreadBase::wait_for() set the thread to sleep until condition 'b' turns true +// wait_for() set the thread to sleep until condition 'b' turns true void ThreadBase::wait_for(volatile const bool& b) { @@ -90,9 +92,43 @@ Thread::Thread() /* : splitPoints() */ { // Value-initialization bug in MSVC } +// cutoff_occurred() checks whether a beta cutoff has occurred in the +// current active split point, or in some ancestor of the split point. + +bool Thread::cutoff_occurred() const { + + for (SplitPoint* sp = activeSplitPoint; sp; sp = sp->parentSplitPoint) + if (sp->cutoff) + return true; + + return false; +} + + +// Thread::available_to() checks whether the thread is available to help the +// thread 'master' at a split point. An obvious requirement is that thread must +// be idle. With more than two threads, this is not sufficient: If the thread is +// the master of some split point, it is only available as a slave to the slaves +// which are busy searching the split point at the top of slave's split point +// stack (the "helpful master concept" in YBWC terminology). + +bool Thread::available_to(const Thread* master) const { + + if (searching) + return false; + + // Make a local copy to be sure it doesn't become zero under our feet while + // testing next condition and so leading to an out of bounds access. + int size = splitPointsSize; + + // No split points means that the thread is available as a slave for any + // other thread otherwise apply the "helpful master" concept if possible. + return !size || (splitPoints[size - 1].slavesMask & (1ULL << master->idx)); +} + + // TimerThread::idle_loop() is where the timer thread waits msec milliseconds // and then calls check_time(). If msec is 0 thread sleeps until it's woken up. -extern void check_time(); void TimerThread::idle_loop() { @@ -144,41 +180,6 @@ void MainThread::idle_loop() { } -// Thread::cutoff_occurred() checks whether a beta cutoff has occurred in the -// current active split point, or in some ancestor of the split point. - -bool Thread::cutoff_occurred() const { - - for (SplitPoint* sp = activeSplitPoint; sp; sp = sp->parentSplitPoint) - if (sp->cutoff) - return true; - - return false; -} - - -// Thread::available_to() checks whether the thread is available to help the -// thread 'master' at a split point. An obvious requirement is that thread must -// be idle. With more than two threads, this is not sufficient: If the thread is -// the master of some split point, it is only available as a slave to the slaves -// which are busy searching the split point at the top of slave's split point -// stack (the "helpful master concept" in YBWC terminology). - -bool Thread::available_to(const Thread* master) const { - - if (searching) - return false; - - // Make a local copy to be sure it doesn't become zero under our feet while - // testing next condition and so leading to an out of bounds access. - int size = splitPointsSize; - - // No split points means that the thread is available as a slave for any - // other thread otherwise apply the "helpful master" concept if possible. - return !size || (splitPoints[size - 1].slavesMask & (1ULL << master->idx)); -} - - // init() is called at startup to create and launch requested threads, that will // go immediately to sleep due to 'sleepWhileIdle' set to true. We cannot use // a c'tor because Threads is a static object and we need a fully initialized @@ -218,12 +219,9 @@ void ThreadPool::read_uci_options() { assert(requested > 0); - // Value 0 has a special meaning: We determine the optimal minimum split depth - // automatically. Anyhow the minimumSplitDepth should never be under 4 plies. + // If zero (default) then set best minimum split depth automatically if (!minimumSplitDepth) - minimumSplitDepth = (requested < 8 ? 4 : 7) * ONE_PLY; - else - minimumSplitDepth = std::max(4 * ONE_PLY, minimumSplitDepth); + minimumSplitDepth = requested < 8 ? 4 * ONE_PLY : 7 * ONE_PLY; while (size() < requested) push_back(new_thread()); @@ -236,7 +234,7 @@ void ThreadPool::read_uci_options() { } -// slave_available() tries to find an idle thread which is available as a slave +// available_slave() tries to find an idle thread which is available as a slave // for the thread 'master'. Thread* ThreadPool::available_slave(const Thread* master) const { @@ -264,8 +262,7 @@ void Thread::split(Position& pos, const Stack* ss, Value alpha, Value beta, Valu MovePicker* movePicker, int nodeType, bool cutNode) { assert(pos.pos_is_ok()); - assert(*bestValue <= alpha && alpha < beta && beta <= VALUE_INFINITE); - assert(*bestValue > -VALUE_INFINITE); + assert(-VALUE_INFINITE < *bestValue && *bestValue <= alpha && alpha < beta && beta <= VALUE_INFINITE); assert(depth >= Threads.minimumSplitDepth); assert(searching); assert(splitPointsSize < MAX_SPLITPOINTS_PER_THREAD); @@ -367,8 +364,8 @@ void ThreadPool::wait_for_think_finished() { // start_thinking() wakes up the main thread sleeping in MainThread::idle_loop() // so to start a new search, then returns immediately. -void ThreadPool::start_thinking(const Position& pos, const LimitsType& limits, - const std::vector& searchMoves, StateStackPtr& states) { +void ThreadPool::start_thinking(const Position& pos, const LimitsType& limits, StateStackPtr& states) { + wait_for_think_finished(); SearchTime = Time::now(); // As early as possible @@ -386,8 +383,8 @@ void ThreadPool::start_thinking(const Position& pos, const LimitsType& limits, } for (MoveList it(pos); *it; ++it) - if ( searchMoves.empty() - || std::count(searchMoves.begin(), searchMoves.end(), *it)) + if ( limits.searchmoves.empty() + || std::count(limits.searchmoves.begin(), limits.searchmoves.end(), *it)) RootMoves.push_back(RootMove(*it)); main()->thinking = true;