1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-04-29 16:23:09 +00:00

Remove the dependency on a Worker from evaluate

Also remove dead code, `rootSimpleEval` is no longer used since the introduction of dual net.
`iterBestValue` is also no longer used in evaluate and can be reduced to a local variable.

closes https://github.com/official-stockfish/Stockfish/pull/4979

No functional change
This commit is contained in:
Disservin 2024-01-13 20:19:33 +01:00
parent 12e97701b2
commit 88331add0d
6 changed files with 29 additions and 44 deletions

View file

@ -35,7 +35,6 @@
#include "nnue/evaluate_nnue.h" #include "nnue/evaluate_nnue.h"
#include "nnue/nnue_architecture.h" #include "nnue/nnue_architecture.h"
#include "position.h" #include "position.h"
#include "search.h"
#include "types.h" #include "types.h"
#include "uci.h" #include "uci.h"
#include "ucioption.h" #include "ucioption.h"
@ -196,7 +195,7 @@ int Eval::simple_eval(const Position& pos, Color c) {
// Evaluate is the evaluator for the outer world. It returns a static evaluation // Evaluate is the evaluator for the outer world. It returns a static evaluation
// of the position from the point of view of the side to move. // of the position from the point of view of the side to move.
Value Eval::evaluate(const Position& pos, const Search::Worker& workerThread) { Value Eval::evaluate(const Position& pos, int optimism) {
assert(!pos.checkers()); assert(!pos.checkers());
@ -217,8 +216,6 @@ Value Eval::evaluate(const Position& pos, const Search::Worker& workerThread) {
Value nnue = smallNet ? NNUE::evaluate<NNUE::Small>(pos, true, &nnueComplexity) Value nnue = smallNet ? NNUE::evaluate<NNUE::Small>(pos, true, &nnueComplexity)
: NNUE::evaluate<NNUE::Big>(pos, true, &nnueComplexity); : NNUE::evaluate<NNUE::Big>(pos, true, &nnueComplexity);
int optimism = workerThread.optimism[stm];
// Blend optimism and eval with nnue complexity and material imbalance // Blend optimism and eval with nnue complexity and material imbalance
optimism += optimism * (nnueComplexity + std::abs(simpleEval - nnue)) / 512; optimism += optimism * (nnueComplexity + std::abs(simpleEval - nnue)) / 512;
nnue -= nnue * (nnueComplexity + std::abs(simpleEval - nnue)) / 32768; nnue -= nnue * (nnueComplexity + std::abs(simpleEval - nnue)) / 32768;
@ -240,17 +237,11 @@ Value Eval::evaluate(const Position& pos, const Search::Worker& workerThread) {
// a string (suitable for outputting to stdout) that contains the detailed // a string (suitable for outputting to stdout) that contains the detailed
// descriptions and values of each evaluation term. Useful for debugging. // descriptions and values of each evaluation term. Useful for debugging.
// Trace scores are from white's point of view // Trace scores are from white's point of view
std::string Eval::trace(Position& pos, Search::Worker& workerThread) { std::string Eval::trace(Position& pos) {
if (pos.checkers()) if (pos.checkers())
return "Final evaluation: none (in check)"; return "Final evaluation: none (in check)";
// Reset any global variable used in eval
workerThread.iterBestValue = VALUE_ZERO;
workerThread.rootSimpleEval = VALUE_ZERO;
workerThread.optimism[WHITE] = VALUE_ZERO;
workerThread.optimism[BLACK] = VALUE_ZERO;
std::stringstream ss; std::stringstream ss;
ss << std::showpoint << std::noshowpos << std::fixed << std::setprecision(2); ss << std::showpoint << std::noshowpos << std::fixed << std::setprecision(2);
ss << '\n' << NNUE::trace(pos) << '\n'; ss << '\n' << NNUE::trace(pos) << '\n';
@ -262,7 +253,7 @@ std::string Eval::trace(Position& pos, Search::Worker& workerThread) {
v = pos.side_to_move() == WHITE ? v : -v; v = pos.side_to_move() == WHITE ? v : -v;
ss << "NNUE evaluation " << 0.01 * UCI::to_cp(v) << " (white side)\n"; ss << "NNUE evaluation " << 0.01 * UCI::to_cp(v) << " (white side)\n";
v = evaluate(pos, workerThread); v = evaluate(pos, VALUE_ZERO);
v = pos.side_to_move() == WHITE ? v : -v; v = pos.side_to_move() == WHITE ? v : -v;
ss << "Final evaluation " << 0.01 * UCI::to_cp(v) << " (white side)"; ss << "Final evaluation " << 0.01 * UCI::to_cp(v) << " (white side)";
ss << " [with scaled NNUE, ...]"; ss << " [with scaled NNUE, ...]";

View file

@ -29,16 +29,12 @@ namespace Stockfish {
class Position; class Position;
class OptionsMap; class OptionsMap;
namespace Search {
class Worker;
}
namespace Eval { namespace Eval {
std::string trace(Position& pos, Search::Worker& workerThread); std::string trace(Position& pos);
int simple_eval(const Position& pos, Color c); int simple_eval(const Position& pos, Color c);
Value evaluate(const Position& pos, const Search::Worker& workerThread); Value evaluate(const Position& pos, int optimism);
// The default net name MUST follow the format nn-[SHA256 first 12 digits].nnue // The default net name MUST follow the format nn-[SHA256 first 12 digits].nnue
// for the build process (profile-build and fishtest) to work. Do not change the // for the build process (profile-build and fishtest) to work. Do not change the

View file

@ -280,7 +280,7 @@ void Search::Worker::iterative_deepening() {
ss->pv = pv; ss->pv = pv;
iterBestValue = -VALUE_INFINITE; Value bestValue = -VALUE_INFINITE;
if (mainThread) if (mainThread)
{ {
@ -357,7 +357,7 @@ void Search::Worker::iterative_deepening() {
// for every four searchAgain steps (see issue #2717). // for every four searchAgain steps (see issue #2717).
Depth adjustedDepth = Depth adjustedDepth =
std::max(1, rootDepth - failedHighCnt - 3 * (searchAgainCounter + 1) / 4); std::max(1, rootDepth - failedHighCnt - 3 * (searchAgainCounter + 1) / 4);
iterBestValue = search<Root>(rootPos, ss, alpha, beta, adjustedDepth, false); bestValue = search<Root>(rootPos, ss, alpha, beta, adjustedDepth, false);
// Bring the best move to the front. It is critical that sorting // Bring the best move to the front. It is critical that sorting
// is done with a stable algorithm because all the values but the // is done with a stable algorithm because all the values but the
@ -375,7 +375,7 @@ void Search::Worker::iterative_deepening() {
// When failing high/low give some update (without cluttering // When failing high/low give some update (without cluttering
// the UI) before a re-search. // the UI) before a re-search.
if (mainThread && multiPV == 1 && (iterBestValue <= alpha || iterBestValue >= beta) if (mainThread && multiPV == 1 && (bestValue <= alpha || bestValue >= beta)
&& mainThread->tm.elapsed(threads.nodes_searched()) > 3000) && mainThread->tm.elapsed(threads.nodes_searched()) > 3000)
sync_cout << UCI::pv(*this, mainThread->tm.elapsed(threads.nodes_searched()), sync_cout << UCI::pv(*this, mainThread->tm.elapsed(threads.nodes_searched()),
threads.nodes_searched(), threads.tb_hits(), tt.hashfull(), threads.nodes_searched(), threads.tb_hits(), tt.hashfull(),
@ -384,18 +384,18 @@ void Search::Worker::iterative_deepening() {
// In case of failing low/high increase aspiration window and // In case of failing low/high increase aspiration window and
// re-search, otherwise exit the loop. // re-search, otherwise exit the loop.
if (iterBestValue <= alpha) if (bestValue <= alpha)
{ {
beta = (alpha + beta) / 2; beta = (alpha + beta) / 2;
alpha = std::max(iterBestValue - delta, -VALUE_INFINITE); alpha = std::max(bestValue - delta, -VALUE_INFINITE);
failedHighCnt = 0; failedHighCnt = 0;
if (mainThread) if (mainThread)
mainThread->stopOnPonderhit = false; mainThread->stopOnPonderhit = false;
} }
else if (iterBestValue >= beta) else if (bestValue >= beta)
{ {
beta = std::min(iterBestValue + delta, int(VALUE_INFINITE)); beta = std::min(bestValue + delta, int(VALUE_INFINITE));
++failedHighCnt; ++failedHighCnt;
} }
else else
@ -428,8 +428,8 @@ void Search::Worker::iterative_deepening() {
} }
// Have we found a "mate in x"? // Have we found a "mate in x"?
if (limits.mate && iterBestValue >= VALUE_MATE_IN_MAX_PLY if (limits.mate && bestValue >= VALUE_MATE_IN_MAX_PLY
&& VALUE_MATE - iterBestValue <= 2 * limits.mate) && VALUE_MATE - bestValue <= 2 * limits.mate)
threads.stop = true; threads.stop = true;
if (!mainThread) if (!mainThread)
@ -449,8 +449,8 @@ void Search::Worker::iterative_deepening() {
// Do we have time for the next iteration? Can we stop searching now? // Do we have time for the next iteration? Can we stop searching now?
if (limits.use_time_management() && !threads.stop && !mainThread->stopOnPonderhit) if (limits.use_time_management() && !threads.stop && !mainThread->stopOnPonderhit)
{ {
double fallingEval = (66 + 14 * (mainThread->bestPreviousAverageScore - iterBestValue) double fallingEval = (66 + 14 * (mainThread->bestPreviousAverageScore - bestValue)
+ 6 * (mainThread->iterValue[iterIdx] - iterBestValue)) + 6 * (mainThread->iterValue[iterIdx] - bestValue))
/ 616.6; / 616.6;
fallingEval = std::clamp(fallingEval, 0.51, 1.51); fallingEval = std::clamp(fallingEval, 0.51, 1.51);
@ -483,7 +483,7 @@ void Search::Worker::iterative_deepening() {
threads.increaseDepth = true; threads.increaseDepth = true;
} }
mainThread->iterValue[iterIdx] = iterBestValue; mainThread->iterValue[iterIdx] = bestValue;
iterIdx = (iterIdx + 1) & 3; iterIdx = (iterIdx + 1) & 3;
} }
@ -580,7 +580,7 @@ Value Search::Worker::search(
// Step 2. Check for aborted search and immediate draw // Step 2. Check for aborted search and immediate draw
if (threads.stop.load(std::memory_order_relaxed) || pos.is_draw(ss->ply) if (threads.stop.load(std::memory_order_relaxed) || pos.is_draw(ss->ply)
|| ss->ply >= MAX_PLY) || ss->ply >= MAX_PLY)
return (ss->ply >= MAX_PLY && !ss->inCheck) ? evaluate(pos, *thisThread) return (ss->ply >= MAX_PLY && !ss->inCheck) ? evaluate(pos, thisThread->optimism[us])
: value_draw(thisThread->nodes); : value_draw(thisThread->nodes);
// Step 3. Mate distance pruning. Even if we mate at the next move our score // Step 3. Mate distance pruning. Even if we mate at the next move our score
@ -734,7 +734,7 @@ Value Search::Worker::search(
// Never assume anything about values stored in TT // Never assume anything about values stored in TT
unadjustedStaticEval = ss->staticEval = eval = tte->eval(); unadjustedStaticEval = ss->staticEval = eval = tte->eval();
if (eval == VALUE_NONE) if (eval == VALUE_NONE)
unadjustedStaticEval = ss->staticEval = eval = evaluate(pos, *thisThread); unadjustedStaticEval = ss->staticEval = eval = evaluate(pos, thisThread->optimism[us]);
else if (PvNode) else if (PvNode)
Eval::NNUE::hint_common_parent_position(pos); Eval::NNUE::hint_common_parent_position(pos);
@ -752,7 +752,7 @@ Value Search::Worker::search(
} }
else else
{ {
unadjustedStaticEval = ss->staticEval = eval = evaluate(pos, *thisThread); unadjustedStaticEval = ss->staticEval = eval = evaluate(pos, thisThread->optimism[us]);
Value newEval = Value newEval =
ss->staticEval ss->staticEval
@ -1470,7 +1470,8 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta,
// Step 2. Check for an immediate draw or maximum ply reached // Step 2. Check for an immediate draw or maximum ply reached
if (pos.is_draw(ss->ply) || ss->ply >= MAX_PLY) if (pos.is_draw(ss->ply) || ss->ply >= MAX_PLY)
return (ss->ply >= MAX_PLY && !ss->inCheck) ? evaluate(pos, *thisThread) : VALUE_DRAW; return (ss->ply >= MAX_PLY && !ss->inCheck) ? evaluate(pos, thisThread->optimism[us])
: VALUE_DRAW;
assert(0 <= ss->ply && ss->ply < MAX_PLY); assert(0 <= ss->ply && ss->ply < MAX_PLY);
@ -1501,7 +1502,8 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta,
{ {
// Never assume anything about values stored in TT // Never assume anything about values stored in TT
if ((unadjustedStaticEval = ss->staticEval = bestValue = tte->eval()) == VALUE_NONE) if ((unadjustedStaticEval = ss->staticEval = bestValue = tte->eval()) == VALUE_NONE)
unadjustedStaticEval = ss->staticEval = bestValue = evaluate(pos, *thisThread); unadjustedStaticEval = ss->staticEval = bestValue =
evaluate(pos, thisThread->optimism[us]);
Value newEval = Value newEval =
ss->staticEval ss->staticEval
@ -1521,7 +1523,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta,
{ {
// In case of null move search, use previous static eval with a different sign // In case of null move search, use previous static eval with a different sign
unadjustedStaticEval = ss->staticEval = bestValue = unadjustedStaticEval = ss->staticEval = bestValue =
(ss - 1)->currentMove != Move::null() ? evaluate(pos, *thisThread) (ss - 1)->currentMove != Move::null() ? evaluate(pos, thisThread->optimism[us])
: -(ss - 1)->staticEval; : -(ss - 1)->staticEval;
Value newEval = Value newEval =

View file

@ -184,10 +184,6 @@ class Worker {
bool is_mainthread() const { return thread_idx == 0; } bool is_mainthread() const { return thread_idx == 0; }
// Public because evaluate uses this
Value iterBestValue, optimism[COLOR_NB];
Value rootSimpleEval;
// Public because they need to be updatable by the stats // Public because they need to be updatable by the stats
CounterMoveHistory counterMoves; CounterMoveHistory counterMoves;
ButterflyHistory mainHistory; ButterflyHistory mainHistory;
@ -226,6 +222,8 @@ class Worker {
std::atomic<uint64_t> nodes, tbHits, bestMoveChanges; std::atomic<uint64_t> nodes, tbHits, bestMoveChanges;
int selDepth, nmpMinPly; int selDepth, nmpMinPly;
Value optimism[COLOR_NB];
Position rootPos; Position rootPos;
StateInfo rootState; StateInfo rootState;
RootMoves rootMoves; RootMoves rootMoves;

View file

@ -27,7 +27,6 @@
#include <unordered_map> #include <unordered_map>
#include <utility> #include <utility>
#include "evaluate.h"
#include "misc.h" #include "misc.h"
#include "movegen.h" #include "movegen.h"
#include "search.h" #include "search.h"
@ -205,8 +204,7 @@ void ThreadPool::start_thinking(const OptionsMap& options,
th->worker->rootDepth = th->worker->completedDepth = 0; th->worker->rootDepth = th->worker->completedDepth = 0;
th->worker->rootMoves = rootMoves; th->worker->rootMoves = rootMoves;
th->worker->rootPos.set(pos.fen(), pos.is_chess960(), &th->worker->rootState); th->worker->rootPos.set(pos.fen(), pos.is_chess960(), &th->worker->rootState);
th->worker->rootState = setupStates->back(); th->worker->rootState = setupStates->back();
th->worker->rootSimpleEval = Eval::simple_eval(pos, pos.side_to_move());
} }
main_thread()->start_searching(); main_thread()->start_searching();

View file

@ -270,7 +270,7 @@ void UCI::trace_eval(Position& pos) {
Eval::NNUE::verify(options, evalFiles); Eval::NNUE::verify(options, evalFiles);
sync_cout << "\n" << Eval::trace(p, *threads.main_thread()->worker.get()) << sync_endl; sync_cout << "\n" << Eval::trace(p) << sync_endl;
} }
void UCI::search_clear() { void UCI::search_clear() {