X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=84c62eec33081a422b10c66eb2462fff5b673b69;hp=e8809f149170c31ceeea0ff821cd2751932506df;hb=1a414cd9cb274d9572c60fe4067671cd993ffb36;hpb=9f94d2280110a1ba5eb9eb15b0756883037a817d diff --git a/src/search.cpp b/src/search.cpp index e8809f14..84c62eec 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -26,7 +26,6 @@ #include "book.h" #include "evaluate.h" -#include "history.h" #include "movegen.h" #include "movepick.h" #include "notation.h" @@ -87,7 +86,8 @@ namespace { TimeManager TimeMgr; int BestMoveChanges; Value DrawValue[COLOR_NB]; - History H; + History Hist; + Gains Gain; template Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth); @@ -99,8 +99,8 @@ 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); + bool allows(const Position& pos, Move first, Move second); + bool refutes(const Position& pos, Move first, Move second); string uci_pv(const Position& pos, int depth, Value alpha, Value beta); struct Skill { @@ -229,22 +229,22 @@ void Search::think() { // 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]->maxPly = 0; 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()->msec = + Threads.timer->msec = Limits.use_time_management() ? std::min(100, std::max(TimeMgr.available_time() / 16, TimerResolution)) : Limits.nodes ? 2 * TimerResolution : 100; - Threads.timer_thread()->notify_one(); // Wake up the recurring timer + Threads.timer->notify_one(); // Wake up the recurring timer id_loop(RootPos); // Let's start searching ! - Threads.timer_thread()->msec = 0; // Stop the timer + Threads.timer->msec = 0; // Stop the timer Threads.sleepWhileIdle = true; // Send idle threads to sleep if (Options["Use Search Log"]) @@ -300,7 +300,8 @@ namespace { bestValue = delta = -VALUE_INFINITE; ss->currentMove = MOVE_NULL; // Hack to skip update gains TT.new_search(); - H.clear(); + Hist.clear(); + Gain.clear(); PVSize = Options["MultiPV"]; Skill skill(Options["Skill Level"]); @@ -399,6 +400,7 @@ namespace { // Sort the PV lines searched so far and update the GUI sort(RootMoves.begin(), RootMoves.begin() + PVIdx + 1); + if (PVIdx + 1 == PVSize || Time::now() - SearchTime > 3000) sync_cout << uci_pv(pos, depth, alpha, beta) << sync_endl; } @@ -618,7 +620,7 @@ namespace { && type_of(move) == NORMAL) { Square to = to_sq(move); - H.update_gain(pos.piece_on(to), to, -(ss-1)->staticEval - ss->staticEval); + Gain.update(pos.piece_on(to), to, -(ss-1)->staticEval - ss->staticEval); } // Step 6. Razoring (is omitted in PV nodes) @@ -705,7 +707,7 @@ namespace { if ( depth < 5 * ONE_PLY && (ss-1)->reduction && threatMove != MOVE_NONE - && allows_move(pos, (ss-1)->currentMove, threatMove)) + && allows(pos, (ss-1)->currentMove, threatMove)) return beta - 1; } } @@ -728,7 +730,7 @@ namespace { assert((ss-1)->currentMove != MOVE_NONE); assert((ss-1)->currentMove != MOVE_NULL); - MovePicker mp(pos, ttMove, H, pos.captured_piece_type()); + MovePicker mp(pos, ttMove, Hist, pos.captured_piece_type()); CheckInfo ci(pos); while ((move = mp.next_move()) != MOVE_NONE) @@ -760,7 +762,7 @@ namespace { split_point_start: // At split points actual search starts from here - MovePicker mp(pos, ttMove, depth, H, ss, PvNode ? -VALUE_INFINITE : beta); + MovePicker mp(pos, ttMove, depth, Hist, ss, PvNode ? -VALUE_INFINITE : beta); CheckInfo ci(pos); value = bestValue; // Workaround a bogus 'uninitialized' warning under gcc singularExtensionNode = !RootNode @@ -866,7 +868,7 @@ split_point_start: // At split points actual search starts from here // Move count based pruning if ( depth < 16 * ONE_PLY && moveCount >= FutilityMoveCounts[depth] - && (!threatMove || !prevents_move(pos, move, threatMove))) + && (!threatMove || !refutes(pos, move, threatMove))) { if (SpNode) sp->mutex.lock(); @@ -879,7 +881,7 @@ split_point_start: // At split points actual search starts from here // but fixing this made program slightly weaker. Depth predictedDepth = newDepth - reduction(depth, moveCount); futilityValue = ss->staticEval + ss->evalMargin + futility_margin(predictedDepth, moveCount) - + H.gain(pos.piece_moved(move), to_sq(move)); + + Gain[pos.piece_moved(move)][to_sq(move)]; if (futilityValue < beta) { @@ -921,8 +923,9 @@ split_point_start: // At split points actual search starts from here && !pvMove && !captureOrPromotion && !dangerous - && ss->killers[0] != move - && ss->killers[1] != move) + && move != ttMove + && move != ss->killers[0] + && move != ss->killers[1]) { ss->reduction = reduction(depth, moveCount); Depth d = std::max(newDepth - ss->reduction, ONE_PLY); @@ -1027,8 +1030,8 @@ split_point_start: // At split points actual search starts from here { assert(bestValue < beta); - bestValue = Threads.split(pos, ss, alpha, beta, bestValue, &bestMove, - depth, threatMove, moveCount, mp, NT); + bestValue = thisThread->split(pos, ss, alpha, beta, bestValue, &bestMove, + depth, threatMove, moveCount, mp, NT); if (bestValue >= beta) break; } @@ -1071,13 +1074,13 @@ split_point_start: // At split points actual search starts from here // Increase history value of the cut-off move Value bonus = Value(int(depth) * int(depth)); - H.add(pos.piece_moved(bestMove), to_sq(bestMove), bonus); + Hist.update(pos.piece_moved(bestMove), to_sq(bestMove), bonus); // Decrease history of all the other played non-capture moves for (int i = 0; i < playedMoveCount - 1; i++) { Move m = movesSearched[i]; - H.add(pos.piece_moved(m), to_sq(m), -bonus); + Hist.update(pos.piece_moved(m), to_sq(m), -bonus); } } } @@ -1189,7 +1192,7 @@ split_point_start: // At split points actual search starts from here // to search the moves. Because the depth is <= 0 here, only captures, // queen promotions and checks (only if depth >= DEPTH_QS_CHECKS) will // be generated. - MovePicker mp(pos, ttMove, depth, H, to_sq((ss-1)->currentMove)); + MovePicker mp(pos, ttMove, depth, Hist, to_sq((ss-1)->currentMove)); CheckInfo ci(pos); // Loop through the moves until no moves remain or a beta cutoff occurs @@ -1366,12 +1369,12 @@ 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 + // allows() tests whether the 'first' move at previous ply somehow makes the + // 'second' move possible, for instance if the moving piece is the same in + // both moves. Normally the second move is the threat (the best move returned // from a null search that fails low). - bool allows_move(const Position& pos, Move first, Move second) { + bool allows(const Position& pos, Move first, Move second) { assert(is_ok(first)); assert(is_ok(second)); @@ -1407,12 +1410,11 @@ split_point_start: // At split points actual search starts from here } - // 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 - // that fails low). + // refutes() tests whether a 'first' move is able to defend against a 'second' + // opponent's move. In this case will not be pruned. Normally the second move + // is the threat (the best move returned from a null search that fails low). - bool prevents_move(const Position& pos, Move first, Move second) { + bool refutes(const Position& pos, Move first, Move second) { assert(is_ok(first)); assert(is_ok(second)); @@ -1511,8 +1513,8 @@ split_point_start: // At split points actual search starts from here int selDepth = 0; for (size_t i = 0; i < Threads.size(); i++) - if (Threads[i].maxPly > selDepth) - selDepth = Threads[i].maxPly; + if (Threads[i]->maxPly > selDepth) + selDepth = Threads[i]->maxPly; for (size_t i = 0; i < uciPVSize; i++) { @@ -1614,7 +1616,7 @@ void Thread::idle_loop() { // at the thread creation. So it means we are the split point's master. const SplitPoint* this_sp = splitPointsSize ? activeSplitPoint : NULL; - assert(!this_sp || (this_sp->master == this && searching)); + assert(!this_sp || (this_sp->masterThread == 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. @@ -1698,11 +1700,11 @@ void Thread::idle_loop() { // 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.sleepWhileIdle - && this != sp->master + && this != sp->masterThread && !sp->slavesMask) { - assert(!sp->master->searching); - sp->master->notify_one(); + assert(!sp->masterThread->searching); + sp->masterThread->notify_one(); } // After releasing the lock we cannot access anymore any SplitPoint @@ -1742,9 +1744,9 @@ void check_time() { // Loop across all split points and sum accumulated SplitPoint nodes plus // all the currently active slaves positions. for (size_t i = 0; i < Threads.size(); i++) - for (int j = 0; j < Threads[i].splitPointsSize; j++) + for (int j = 0; j < Threads[i]->splitPointsSize; j++) { - SplitPoint& sp = Threads[i].splitPoints[j]; + SplitPoint& sp = Threads[i]->splitPoints[j]; sp.mutex.lock();