mirror of
https://github.com/official-stockfish/Stockfish.git
synced 2026-07-22 20:57:10 +00:00
Merge commit '2dbb44e28d2e5b3c72ddbbd6f436d41f75031a22' into cluster
This commit is contained in:
+16
-6
@@ -197,8 +197,8 @@ void Search::Worker::start_searching() {
|
||||
// When playing in 'nodes as time' mode, subtract the searched nodes from
|
||||
// the available ones before exiting.
|
||||
if (limits.npmsec)
|
||||
main_manager()->tm.advance_nodes_time(limits.inc[rootPos.side_to_move()]
|
||||
- Cluster::nodes_searched(threads));
|
||||
main_manager()->tm.advance_nodes_time(Cluster::nodes_searched(threads)
|
||||
- limits.inc[rootPos.side_to_move()]);
|
||||
|
||||
Worker* bestThread = this;
|
||||
Skill skill =
|
||||
@@ -389,7 +389,7 @@ void Search::Worker::iterative_deepening() {
|
||||
// When failing high/low give some update (without cluttering
|
||||
// the UI) before a re-search.
|
||||
if (Cluster::is_root() && mainThread && multiPV == 1
|
||||
&& (bestValue <= alpha || bestValue >= beta) && elapsed() > 3000)
|
||||
&& (bestValue <= alpha || bestValue >= beta) && elapsed_time() > 3000)
|
||||
{
|
||||
main_manager()->pv(*this, threads, tt, rootDepth);
|
||||
Cluster::cluster_info(threads, rootDepth, elapsed());
|
||||
@@ -423,7 +423,7 @@ void Search::Worker::iterative_deepening() {
|
||||
std::stable_sort(rootMoves.begin() + pvFirst, rootMoves.begin() + pvIdx + 1);
|
||||
|
||||
if (Cluster::is_root() && mainThread
|
||||
&& (threads.stop || pvIdx + 1 == multiPV || elapsed() > 3000)
|
||||
&& (threads.stop || pvIdx + 1 == multiPV || elapsed_time() > 3000)
|
||||
// A thread that aborted search can have mated-in/TB-loss PV and score
|
||||
// that cannot be trusted, i.e. it can be delayed or refuted if we would have
|
||||
// had time to fully search other root-moves. Thus we suppress this output and
|
||||
@@ -984,7 +984,7 @@ moves_loop: // When in check, search starts here
|
||||
|
||||
ss->moveCount = ++moveCount;
|
||||
|
||||
if (rootNode && Cluster::is_root() && is_mainthread() && elapsed() > 3000)
|
||||
if (rootNode && Cluster::is_root() && is_mainthread() && elapsed_time() > 3000)
|
||||
{
|
||||
main_manager()->updates.onIter(
|
||||
{depth, UCIEngine::move(move, pos.is_chess960()), moveCount + thisThread->pvIdx});
|
||||
@@ -1701,10 +1701,20 @@ Depth Search::Worker::reduction(bool i, Depth d, int mn, int delta) {
|
||||
return (reductionScale + 1318 - delta * 760 / rootDelta) / 1024 + (!i && reductionScale > 1066);
|
||||
}
|
||||
|
||||
// elapsed() returns the time elapsed since the search started. If the
|
||||
// 'nodestime' option is enabled, it will return the count of nodes searched
|
||||
// instead. This function is called to check whether the search should be
|
||||
// stopped based on predefined thresholds like time limits or nodes searched.
|
||||
//
|
||||
// elapsed_time() returns the actual time elapsed since the start of the search.
|
||||
// This function is intended for use only when printing PV outputs, and not used
|
||||
// for making decisions within the search algorithm itself.
|
||||
TimePoint Search::Worker::elapsed() const {
|
||||
return main_manager()->tm.elapsed([this]() { return Cluster::nodes_searched(threads); });
|
||||
}
|
||||
|
||||
TimePoint Search::Worker::elapsed_time() const { return main_manager()->tm.elapsed_time(); }
|
||||
|
||||
|
||||
namespace {
|
||||
// Adjusts a mate or TB score from "plies to mate from the root"
|
||||
@@ -1958,7 +1968,7 @@ void SearchManager::pv(const Search::Worker& worker,
|
||||
const auto& rootMoves = worker.rootMoves;
|
||||
const auto& pos = worker.rootPos;
|
||||
size_t pvIdx = worker.pvIdx;
|
||||
TimePoint time = tm.elapsed([nodes]() { return nodes; }) + 1;
|
||||
TimePoint time = tm.elapsed_time() + 1;
|
||||
size_t multiPV = std::min(size_t(worker.options["MultiPV"]), rootMoves.size());
|
||||
uint64_t tbHits = Cluster::tb_hits(threads) + (worker.tbConfig.rootInTB ? rootMoves.size() : 0);
|
||||
|
||||
|
||||
@@ -308,6 +308,7 @@ class Worker {
|
||||
}
|
||||
|
||||
TimePoint elapsed() const;
|
||||
TimePoint elapsed_time() const;
|
||||
|
||||
LimitsType limits;
|
||||
|
||||
|
||||
+27
-19
@@ -32,12 +32,12 @@ TimePoint TimeManagement::optimum() const { return optimumTime; }
|
||||
TimePoint TimeManagement::maximum() const { return maximumTime; }
|
||||
|
||||
void TimeManagement::clear() {
|
||||
availableNodes = 0; // When in 'nodes as time' mode
|
||||
availableNodes = -1; // When in 'nodes as time' mode
|
||||
}
|
||||
|
||||
void TimeManagement::advance_nodes_time(std::int64_t nodes) {
|
||||
assert(useNodesTime);
|
||||
availableNodes += nodes;
|
||||
availableNodes = std::max(int64_t(0), availableNodes - nodes);
|
||||
}
|
||||
|
||||
// Called at the beginning of the search and calculates
|
||||
@@ -48,14 +48,17 @@ void TimeManagement::init(Search::LimitsType& limits,
|
||||
Color us,
|
||||
int ply,
|
||||
const OptionsMap& options) {
|
||||
// If we have no time, no need to initialize TM, except for the start time,
|
||||
// which is used by movetime.
|
||||
startTime = limits.startTime;
|
||||
TimePoint npmsec = TimePoint(options["nodestime"]);
|
||||
|
||||
// If we have no time, we don't need to fully initialize TM.
|
||||
// startTime is used by movetime and useNodesTime is used in elapsed calls.
|
||||
startTime = limits.startTime;
|
||||
useNodesTime = npmsec != 0;
|
||||
|
||||
if (limits.time[us] == 0)
|
||||
return;
|
||||
|
||||
TimePoint moveOverhead = TimePoint(options["Move Overhead"]);
|
||||
TimePoint npmsec = TimePoint(options["nodestime"]);
|
||||
|
||||
// optScale is a percentage of available time to use for the current move.
|
||||
// maxScale is a multiplier applied to optimumTime.
|
||||
@@ -65,26 +68,31 @@ void TimeManagement::init(Search::LimitsType& limits,
|
||||
// to nodes, and use resulting values in time management formulas.
|
||||
// WARNING: to avoid time losses, the given npmsec (nodes per millisecond)
|
||||
// must be much lower than the real engine speed.
|
||||
if (npmsec)
|
||||
if (useNodesTime)
|
||||
{
|
||||
useNodesTime = true;
|
||||
|
||||
if (!availableNodes) // Only once at game start
|
||||
if (availableNodes == -1) // Only once at game start
|
||||
availableNodes = npmsec * limits.time[us]; // Time is in msec
|
||||
|
||||
// Convert from milliseconds to nodes
|
||||
limits.time[us] = TimePoint(availableNodes);
|
||||
limits.inc[us] *= npmsec;
|
||||
limits.npmsec = npmsec;
|
||||
moveOverhead *= npmsec;
|
||||
}
|
||||
|
||||
// These numbers are used where multiplications, divisions or comparisons
|
||||
// with constants are involved.
|
||||
const int64_t scaleFactor = useNodesTime ? npmsec : 1;
|
||||
const TimePoint scaledTime = limits.time[us] / scaleFactor;
|
||||
const TimePoint scaledInc = limits.inc[us] / scaleFactor;
|
||||
|
||||
// Maximum move horizon of 50 moves
|
||||
int mtg = limits.movestogo ? std::min(limits.movestogo, 50) : 50;
|
||||
|
||||
// if less than one second, gradually reduce mtg
|
||||
if (limits.time[us] < 1000 && (double(mtg) / limits.time[us] > 0.05))
|
||||
// If less than one second, gradually reduce mtg
|
||||
if (scaledTime < 1000 && double(mtg) / scaledInc > 0.05)
|
||||
{
|
||||
mtg = limits.time[us] * 0.05;
|
||||
mtg = scaledTime * 0.05;
|
||||
}
|
||||
|
||||
// Make sure timeLeft is > 0 since we may use it as a divisor
|
||||
@@ -97,15 +105,15 @@ void TimeManagement::init(Search::LimitsType& limits,
|
||||
if (limits.movestogo == 0)
|
||||
{
|
||||
// Use extra time with larger increments
|
||||
double optExtra = limits.inc[us] < 500 ? 1.0 : 1.13;
|
||||
double optExtra = scaledInc < 500 ? 1.0 : 1.13;
|
||||
|
||||
// Calculate time constants based on current time left.
|
||||
double optConstant =
|
||||
std::min(0.00308 + 0.000319 * std::log10(limits.time[us] / 1000.0), 0.00506);
|
||||
double maxConstant = std::max(3.39 + 3.01 * std::log10(limits.time[us] / 1000.0), 2.93);
|
||||
double logTimeInSec = std::log10(scaledTime / 1000.0);
|
||||
double optConstant = std::min(0.00308 + 0.000319 * logTimeInSec, 0.00506);
|
||||
double maxConstant = std::max(3.39 + 3.01 * logTimeInSec, 2.93);
|
||||
|
||||
optScale = std::min(0.0122 + std::pow(ply + 2.95, 0.462) * optConstant,
|
||||
0.213 * limits.time[us] / double(timeLeft))
|
||||
0.213 * limits.time[us] / timeLeft)
|
||||
* optExtra;
|
||||
maxScale = std::min(6.64, maxConstant + ply / 12.0);
|
||||
}
|
||||
@@ -113,7 +121,7 @@ void TimeManagement::init(Search::LimitsType& limits,
|
||||
// x moves in y seconds (+ z increment)
|
||||
else
|
||||
{
|
||||
optScale = std::min((0.88 + ply / 116.4) / mtg, 0.88 * limits.time[us] / double(timeLeft));
|
||||
optScale = std::min((0.88 + ply / 116.4) / mtg, 0.88 * limits.time[us] / timeLeft);
|
||||
maxScale = std::min(6.3, 1.5 + 0.11 * mtg);
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -42,8 +42,9 @@ class TimeManagement {
|
||||
TimePoint maximum() const;
|
||||
template<typename FUNC>
|
||||
TimePoint elapsed(FUNC nodes) const {
|
||||
return useNodesTime ? TimePoint(nodes()) : now() - startTime;
|
||||
return useNodesTime ? TimePoint(nodes()) : elapsed_time();
|
||||
}
|
||||
TimePoint elapsed_time() const { return now() - startTime; };
|
||||
|
||||
void clear();
|
||||
void advance_nodes_time(std::int64_t nodes);
|
||||
@@ -53,7 +54,7 @@ class TimeManagement {
|
||||
TimePoint optimumTime;
|
||||
TimePoint maximumTime;
|
||||
|
||||
std::int64_t availableNodes = 0; // When in 'nodes as time' mode
|
||||
std::int64_t availableNodes = -1; // When in 'nodes as time' mode
|
||||
bool useNodesTime = false; // True if we are in 'nodes as time' mode
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user