diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 064ea027..248b2593 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -24,8 +24,9 @@ #include #include #include -#include #include +#include +#include #include "nnue/network.h" #include "nnue/nnue_misc.h" @@ -60,17 +61,22 @@ Value Eval::evaluate(const Eval::NNUE::Networks& networks, int simpleEval = simple_eval(pos, pos.side_to_move()); bool smallNet = use_smallnet(pos); - int nnueComplexity; int v; - Value nnue = smallNet ? networks.small.evaluate(pos, &caches.small, true, &nnueComplexity) - : networks.big.evaluate(pos, &caches.big, true, &nnueComplexity); + auto [psqt, positional] = smallNet ? networks.small.evaluate(pos, &caches.small) + : networks.big.evaluate(pos, &caches.big); + + constexpr int delta = 3; + Value nnue = ((128 - delta) * psqt + (128 + delta) * positional) / 128; + int nnueComplexity = std::abs(psqt - positional); // Re-evaluate the position when higher eval accuracy is worth the time spent if (smallNet && (nnue * simpleEval < 0 || std::abs(nnue) < 250)) { - nnue = networks.big.evaluate(pos, &caches.big, true, &nnueComplexity); - smallNet = false; + std::tie(psqt, positional) = networks.big.evaluate(pos, &caches.big); + nnue = ((128 - delta) * psqt + (128 + delta) * positional) / 128; + nnueComplexity = std::abs(psqt - positional); + smallNet = false; } // Blend optimism and eval with nnue complexity @@ -108,8 +114,9 @@ std::string Eval::trace(Position& pos, const Eval::NNUE::Networks& networks) { ss << std::showpoint << std::showpos << std::fixed << std::setprecision(2) << std::setw(15); - Value v = networks.big.evaluate(pos, &caches->big, false); - v = pos.side_to_move() == WHITE ? v : -v; + auto [psqt, positional] = networks.big.evaluate(pos, &caches->big); + Value v = psqt + positional; + v = pos.side_to_move() == WHITE ? v : -v; ss << "NNUE evaluation " << 0.01 * UCIEngine::to_cp(v, pos) << " (white side)\n"; v = evaluate(networks, pos, *caches, VALUE_ZERO); diff --git a/src/nnue/network.cpp b/src/nnue/network.cpp index 71c384ff..f7d2cc6a 100644 --- a/src/nnue/network.cpp +++ b/src/nnue/network.cpp @@ -18,7 +18,6 @@ #include "network.h" -#include #include #include #include @@ -206,15 +205,13 @@ bool Network::save(const std::optional& filename template -Value Network::evaluate(const Position& pos, - AccumulatorCaches::Cache* cache, - bool adjusted, - int* complexity) const { +NetworkOutput +Network::evaluate(const Position& pos, + AccumulatorCaches::Cache* cache) const { // We manually align the arrays on the stack because with gcc < 9.3 // overaligning stack variables with alignas() doesn't work correctly. constexpr uint64_t alignment = CacheLineSize; - constexpr int delta = 24; #if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN) TransformedFeatureType @@ -232,16 +229,7 @@ Value Network::evaluate(const Position& const int bucket = (pos.count() - 1) / 4; const auto psqt = featureTransformer->transform(pos, cache, transformedFeatures, bucket); const auto positional = network[bucket].propagate(transformedFeatures); - - if (complexity) - *complexity = std::abs(psqt - positional) / OutputScale; - - // Give more value to positional evaluation when adjusted flag is set - if (adjusted) - return static_cast(((1024 - delta) * psqt + (1024 + delta) * positional) - / (1024 * OutputScale)); - else - return static_cast((psqt + positional) / OutputScale); + return {static_cast(psqt / OutputScale), static_cast(positional / OutputScale)}; } diff --git a/src/nnue/network.h b/src/nnue/network.h index 6ba3cfba..15208255 100644 --- a/src/nnue/network.h +++ b/src/nnue/network.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "../memory.h" @@ -40,6 +41,7 @@ enum class EmbeddedNNUEType { SMALL, }; +using NetworkOutput = std::tuple; template class Network { @@ -59,10 +61,8 @@ class Network { void load(const std::string& rootDirectory, std::string evalfilePath); bool save(const std::optional& filename) const; - Value evaluate(const Position& pos, - AccumulatorCaches::Cache* cache, - bool adjusted = false, - int* complexity = nullptr) const; + NetworkOutput evaluate(const Position& pos, + AccumulatorCaches::Cache* cache) const; void hint_common_access(const Position& pos, diff --git a/src/nnue/nnue_misc.cpp b/src/nnue/nnue_misc.cpp index a13c717c..7585cce5 100644 --- a/src/nnue/nnue_misc.cpp +++ b/src/nnue/nnue_misc.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include "../evaluate.h" #include "../position.h" @@ -131,8 +132,9 @@ trace(Position& pos, const Eval::NNUE::Networks& networks, Eval::NNUE::Accumulat // We estimate the value of each piece by doing a differential evaluation from // the current base eval, simulating the removal of the piece from its square. - Value base = networks.big.evaluate(pos, &caches.big); - base = pos.side_to_move() == WHITE ? base : -base; + auto [psqt, positional] = networks.big.evaluate(pos, &caches.big); + Value base = psqt + positional; + base = pos.side_to_move() == WHITE ? base : -base; for (File f = FILE_A; f <= FILE_H; ++f) for (Rank r = RANK_1; r <= RANK_8; ++r) @@ -148,9 +150,10 @@ trace(Position& pos, const Eval::NNUE::Networks& networks, Eval::NNUE::Accumulat pos.remove_piece(sq); st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] = false; - Value eval = networks.big.evaluate(pos, &caches.big); - eval = pos.side_to_move() == WHITE ? eval : -eval; - v = base - eval; + std::tie(psqt, positional) = networks.big.evaluate(pos, &caches.big); + Value eval = psqt + positional; + eval = pos.side_to_move() == WHITE ? eval : -eval; + v = base - eval; pos.put_piece(pc, sq); st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] = false;