X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=21db685285972f12c571078dec42751d76201228;hp=516f2d051cc503f058d2f541a7d46ef9fcb8800e;hb=2c317d7b28161e74f0cdc0a00922b48cb996321f;hpb=076b62310ee874adb38d2c9610aad163db65e2e8 diff --git a/src/search.cpp b/src/search.cpp index 516f2d05..21db6852 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -64,6 +64,7 @@ namespace { static storage duration are automatically set to zero before enter main() */ public: + Thread& operator[](int threadID) { return threads[threadID]; } void init_threads(); void exit_threads(); @@ -83,14 +84,13 @@ namespace { Depth depth, Move threatMove, int moveCount, MovePicker* mp, bool pvNode); private: + Lock mpLock; Depth minimumSplitDepth; int maxThreadsPerSplitPoint; bool useSleepingThreads; int activeThreads; volatile bool allThreadsShouldExit; Thread threads[MAX_THREADS]; - Lock mpLock, sleepLock[MAX_THREADS]; - WaitCondition sleepCond[MAX_THREADS]; }; @@ -118,7 +118,7 @@ namespace { void extract_pv_from_tt(Position& pos); void insert_pv_in_tt(Position& pos); - std::string pv_info_to_uci(Position& pos, int depth, Value alpha, Value beta, int pvIdx); + std::string pv_info_to_uci(Position& pos, int depth, int selDepth, Value alpha, Value beta, int pvIdx); int64_t nodes; Value pv_score; @@ -506,9 +506,12 @@ bool think(Position& pos, bool infinite, bool ponder, int time[], int increment[ ThreadsMgr.read_uci_options(); init_eval(ThreadsMgr.active_threads()); - // Wake up needed threads. Main thread, with threadID == 0, is always active - for (int i = 1; i < ThreadsMgr.active_threads(); i++) + // Wake up needed threads and reset maxPly counter + for (int i = 0; i < ThreadsMgr.active_threads(); i++) + { ThreadsMgr.wake_sleeping_thread(i); + ThreadsMgr[i].maxPly = 0; + } // Set thinking time int myTime = time[pos.side_to_move()]; @@ -596,7 +599,7 @@ namespace { SearchStack ss[PLY_MAX_PLUS_2]; Value bestValues[PLY_MAX_PLUS_2]; int bestMoveChanges[PLY_MAX_PLUS_2]; - int depth, aspirationDelta, skillSamplingDepth; + int depth, selDepth, aspirationDelta; Value value, alpha, beta; Move bestMove, easyMove, skillBest, skillPonder; @@ -605,7 +608,7 @@ namespace { TT.new_search(); H.clear(); *ponderMove = bestMove = easyMove = skillBest = skillPonder = MOVE_NONE; - depth = aspirationDelta = skillSamplingDepth = 0; + depth = aspirationDelta = 0; alpha = -VALUE_INFINITE, beta = VALUE_INFINITE; ss->currentMove = MOVE_NULL; // Hack to skip update_gains() @@ -622,11 +625,6 @@ namespace { return MOVE_NONE; } - // Choose a random sampling depth according to SkillLevel so that at low - // skills there is an higher risk to pick up a blunder. - if (SkillLevelEnabled) - skillSamplingDepth = 4 + SkillLevel + (RK.rand() % 4); - // Iterative deepening loop while (++depth <= PLY_MAX && (!MaxDepth || depth <= MaxDepth) && !StopRequest) { @@ -690,12 +688,18 @@ namespace { bestMoveChanges[depth] = Rml.bestMoveChanges; // Do we need to pick now the best and the ponder moves ? - if (SkillLevelEnabled && depth == skillSamplingDepth) + if (SkillLevelEnabled && depth == 1 + SkillLevel) do_skill_level(&skillBest, &skillPonder); + // Retrieve max searched depth among threads + selDepth = 0; + for (int i = 0; i < ThreadsMgr.active_threads(); i++) + if (ThreadsMgr[i].maxPly > selDepth) + selDepth = ThreadsMgr[i].maxPly; + // Send PV line to GUI and to log file for (int i = 0; i < Min(UCIMultiPV, (int)Rml.size()); i++) - cout << Rml[i].pv_info_to_uci(pos, depth, alpha, beta, i) << endl; + cout << Rml[i].pv_info_to_uci(pos, depth, selDepth, alpha, beta, i) << endl; if (UseLogFile) LogFile << pretty_pv(pos, depth, value, current_search_time(), Rml[0].pv) << endl; @@ -798,6 +802,10 @@ namespace { isCheck = pos.is_check(); ss->ply = (ss-1)->ply + 1; + // Used to send selDepth info to GUI + if (PvNode && ThreadsMgr[threadID].maxPly < ss->ply) + ThreadsMgr[threadID].maxPly = ss->ply; + if (SpNode) { sp = ss->sp; @@ -2052,7 +2060,7 @@ split_point_start: // At split points actual search starts from here threads[threadID].state = THREAD_AVAILABLE; // Grab the lock to avoid races with wake_sleeping_thread() - lock_grab(&sleepLock[threadID]); + lock_grab(&threads[threadID].sleepLock); // If we are master and all slaves have finished do not go to sleep for (i = 0; sp && i < activeThreads && !sp->slaves[i]; i++) {} @@ -2060,15 +2068,15 @@ split_point_start: // At split points actual search starts from here if (allFinished || allThreadsShouldExit) { - lock_release(&sleepLock[threadID]); + lock_release(&threads[threadID].sleepLock); break; } // Do sleep here after retesting sleep conditions if (threadID >= activeThreads || threads[threadID].state == THREAD_AVAILABLE) - cond_wait(&sleepCond[threadID], &sleepLock[threadID]); + cond_wait(&threads[threadID].sleepCond, &threads[threadID].sleepLock); - lock_release(&sleepLock[threadID]); + lock_release(&threads[threadID].sleepLock); } // If this thread has been assigned work, launch a search @@ -2139,8 +2147,8 @@ split_point_start: // At split points actual search starts from here for (i = 0; i < MAX_THREADS; i++) { - lock_init(&sleepLock[i]); - cond_init(&sleepCond[i]); + lock_init(&threads[i].sleepLock); + cond_init(&threads[i].sleepCond); } // Initialize splitPoints[] locks @@ -2207,8 +2215,8 @@ split_point_start: // At split points actual search starts from here // Now we can safely destroy the wait conditions for (int i = 0; i < MAX_THREADS; i++) { - lock_destroy(&sleepLock[i]); - cond_destroy(&sleepCond[i]); + lock_destroy(&threads[i].sleepLock); + cond_destroy(&threads[i].sleepCond); } } @@ -2397,9 +2405,9 @@ split_point_start: // At split points actual search starts from here void ThreadsManager::wake_sleeping_thread(int threadID) { - lock_grab(&sleepLock[threadID]); - cond_signal(&sleepCond[threadID]); - lock_release(&sleepLock[threadID]); + lock_grab(&threads[threadID].sleepLock); + cond_signal(&threads[threadID].sleepCond); + lock_release(&threads[threadID].sleepLock); } @@ -2489,21 +2497,20 @@ split_point_start: // At split points actual search starts from here // pv_info_to_uci() returns a string with information on the current PV line // formatted according to UCI specification. - std::string RootMove::pv_info_to_uci(Position& pos, int depth, Value alpha, + std::string RootMove::pv_info_to_uci(Position& pos, int depth, int selDepth, Value alpha, Value beta, int pvIdx) { - std::stringstream s, l; - Move* m = pv; - - while (*m != MOVE_NONE) - l << *m++ << " "; + std::stringstream s; s << "info depth " << depth - << " seldepth " << int(m - pv) + << " seldepth " << selDepth << " multipv " << pvIdx + 1 << " score " << value_to_uci(pv_score) << (pv_score >= beta ? " lowerbound" : pv_score <= alpha ? " upperbound" : "") << speed_to_uci(pos.nodes_searched()) - << " pv " << l.str(); + << " pv "; + + for (Move* m = pv; *m != MOVE_NONE; m++) + s << *m << " "; return s.str(); }