X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=2b04befa09cdea2ed0a1b6cc4529d35c30d1faba;hp=b18ae3539d68239259f82332ea12621b7ec90fba;hb=588670e8d2ed5735300c5549ef754ceb09f1f461;hpb=dda7de17e74d7e80c58b5f86be5c78393ae65541 diff --git a/src/search.cpp b/src/search.cpp index b18ae353..2b04befa 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -99,7 +99,6 @@ namespace { Value value_to_tt(Value v, int ply); Value value_from_tt(Value v, int ply); bool check_is_dangerous(Position& pos, Move move, Value futilityBase, Value beta); - bool allows_move(const Position& pos, Move first, Move second); bool prevents_move(const Position& pos, Move first, Move second); string uci_pv(const Position& pos, int depth, Value alpha, Value beta); @@ -227,19 +226,15 @@ void Search::think() { << std::endl; } - // Reset and wake up the threads + // Reset the threads, still sleeping: will be wake up at split time for (size_t i = 0; i < Threads.size(); i++) - { Threads[i].maxPly = 0; - Threads[i].do_sleep = false; - if (!Threads.use_sleeping_threads()) - Threads[i].notify_one(); - } + Threads.sleepWhileIdle = Options["Use Sleeping Threads"]; // Set best timer interval to avoid lagging under time pressure. Timer is // used to check for remaining available thinking time. - Threads.timer_thread()->maxPly = /* Hack: we use maxPly to set timer interval */ + Threads.timer_thread()->msec = Limits.use_time_management() ? std::min(100, std::max(TimeMgr.available_time() / 16, TimerResolution)) : Limits.nodes ? 2 * TimerResolution : 100; @@ -248,12 +243,8 @@ void Search::think() { id_loop(RootPos); // Let's start searching ! - Threads.timer_thread()->maxPly = 0; // Stop the timer - - // Main thread will go to sleep by itself to avoid a race with start_searching() - for (size_t i = 0; i < Threads.size(); i++) - if (&Threads[i] != Threads.main_thread()) - Threads[i].do_sleep = true; + Threads.timer_thread()->msec = 0; // Stop the timer + Threads.sleepWhileIdle = true; // Send idle threads to sleep if (Options["Use Search Log"]) { @@ -507,13 +498,12 @@ namespace { Value bestValue, value, ttValue; Value eval, nullValue, futilityValue; bool inCheck, givesCheck, pvMove, singularExtensionNode; - bool captureOrPromotion, dangerous, doFullDepthSearch, threatExtension; + bool captureOrPromotion, dangerous, doFullDepthSearch; int moveCount, playedMoveCount; // Step 1. Initialize node Thread* thisThread = pos.this_thread(); moveCount = playedMoveCount = 0; - threatExtension = false; inCheck = pos.checkers(); if (SpNode) @@ -702,20 +692,9 @@ namespace { return nullValue; } else - { // The null move failed low, which means that we may be faced with - // some kind of threat. If the previous move was reduced, check if - // the move that refuted the null move was somehow connected to the - // move which was reduced. If a connection is found extend moves that - // defend against threat. + // some kind of threat. threatMove = (ss+1)->currentMove; - - if ( depth < 5 * ONE_PLY - && (ss-1)->reduction - && threatMove != MOVE_NONE - && allows_move(pos, (ss-1)->currentMove, threatMove)) - threatExtension = true; - } } // Step 9. ProbCut (is omitted in PV nodes) @@ -832,9 +811,6 @@ split_point_start: // At split points actual search starts from here if (PvNode && dangerous) ext = ONE_PLY; - else if (threatExtension && prevents_move(pos, move, threatMove)) - ext = ONE_PLY; - else if (givesCheck && pos.see_sign(move) >= 0) ext = ONE_PLY / 2; @@ -871,13 +847,12 @@ split_point_start: // At split points actual search starts from here && !inCheck && !dangerous && move != ttMove + && (!threatMove || !prevents_move(pos, move, threatMove)) && (bestValue > VALUE_MATED_IN_MAX_PLY || ( bestValue == -VALUE_INFINITE && alpha > VALUE_MATED_IN_MAX_PLY))) { // Move count based pruning - if ( depth < 16 * ONE_PLY - && moveCount >= FutilityMoveCounts[depth] - && (!threatMove || !prevents_move(pos, move, threatMove))) + if (depth < 16 * ONE_PLY && moveCount >= FutilityMoveCounts[depth]) { if (SpNode) sp->mutex.lock(); @@ -1032,7 +1007,7 @@ split_point_start: // At split points actual search starts from here // Step 19. Check for splitting the search if ( !SpNode - && depth >= Threads.min_split_depth() + && depth >= Threads.minimumSplitDepth && Threads.available_slave_exists(thisThread)) { assert(bestValue < beta); @@ -1376,47 +1351,6 @@ split_point_start: // At split points actual search starts from here } - // allows_move() tests whether the move at previous ply (first) somehow makes a - // second move possible, for instance if the moving piece is the same in both - // moves. Normally the second move is the threat move (the best move returned - // from a null search that fails low). - - bool allows_move(const Position& pos, Move first, Move second) { - - assert(is_ok(first)); - assert(is_ok(second)); - assert(color_of(pos.piece_on(from_sq(second))) == ~pos.side_to_move()); - assert(color_of(pos.piece_on(to_sq(first))) == ~pos.side_to_move()); - - Square m1from = from_sq(first); - Square m2from = from_sq(second); - Square m1to = to_sq(first); - Square m2to = to_sq(second); - - // The piece is the same or second's destination was vacated by the first move - if (m1to == m2from || m2to == m1from) - return true; - - // Second one moves through the square vacated by first one - if (between_bb(m2from, m2to) & m1from) - return true; - - // Second's destination is defended by the first move's piece - Bitboard m1att = pos.attacks_from(pos.piece_on(m1to), m1to, pos.pieces() ^ m2from); - if (m1att & m2to) - return true; - - // Second move gives a discovered check through the first's checking piece - if (m1att & pos.king_square(pos.side_to_move())) - { - assert(between_bb(m1to, pos.king_square(pos.side_to_move())) & m2from); - return true; - } - - return false; - } - - // prevents_move() tests whether a move (first) is able to defend against an // opponent's move (second). In this case will not be pruned. Normally the // second move is the threat move (the best move returned from a null search @@ -1624,7 +1558,7 @@ void Thread::idle_loop() { // object for which the thread is the master. const SplitPoint* sp_master = splitPointsCnt ? curSplitPoint : NULL; - assert(!sp_master || (sp_master->master == this && is_searching)); + assert(!sp_master || (sp_master->master == this && searching)); // 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. @@ -1632,11 +1566,9 @@ void Thread::idle_loop() { { // If we are not searching, wait for a condition to be signaled // instead of wasting CPU time polling for work. - while ( do_sleep - || do_exit - || (!is_searching && Threads.use_sleeping_threads())) + while ((!searching && Threads.sleepWhileIdle) || exit) { - if (do_exit) + if (exit) { assert(!sp_master); return; @@ -1656,20 +1588,20 @@ void Thread::idle_loop() { // particular we need to avoid a deadlock in case a master thread has, // in the meanwhile, allocated us and sent the wake_up() call before we // had the chance to grab the lock. - if (do_sleep || !is_searching) + if (!searching && !exit) sleepCondition.wait(mutex); mutex.unlock(); } // If this thread has been assigned work, launch a search - if (is_searching) + if (searching) { - assert(!do_sleep && !do_exit); + assert(!exit); Threads.mutex.lock(); - assert(is_searching); + assert(searching); SplitPoint* sp = curSplitPoint; Threads.mutex.unlock(); @@ -1695,20 +1627,20 @@ void Thread::idle_loop() { else assert(false); - assert(is_searching); + assert(searching); - is_searching = false; + searching = false; sp->activePositions[idx] = NULL; sp->slavesMask &= ~(1ULL << idx); sp->nodes += pos.nodes_searched(); // 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 ( Threads.use_sleeping_threads() + if ( Threads.sleepWhileIdle && this != sp->master && !sp->slavesMask) { - assert(!sp->master->is_searching); + assert(!sp->master->searching); sp->master->notify_one(); }