mirror of
https://github.com/HChaZZY/Stockfish.git
synced 2025-12-23 02:27:00 +08:00
Implement accumulator refresh table
For each thread persist an accumulator cache for the network, where each cache contains multiple entries for each of the possible king squares. When the accumulator needs to be refreshed, the cached entry is used to more efficiently update the accumulator, instead of rebuilding it from scratch. This idea, was first described by Luecx (author of Koivisto) and is commonly referred to as "Finny Tables". When the accumulator needs to be refreshed, instead of filling it with biases and adding every piece from scratch, we... 1. Take the `AccumulatorRefreshEntry` associated with the new king bucket 2. Calculate the features to activate and deactivate (from differences between bitboards in the entry and bitboards of the actual position) 3. Apply the updates on the refresh entry 4. Copy the content of the refresh entry accumulator to the accumulator we were refreshing 5. Copy the bitboards from the position to the refresh entry, to match the newly updated accumulator Results at STC: https://tests.stockfishchess.org/tests/view/662301573fe04ce4cefc1386 (first version) https://tests.stockfishchess.org/tests/view/6627fa063fe04ce4cefc6560 (final) Non-Regression between first and final: https://tests.stockfishchess.org/tests/view/662801e33fe04ce4cefc660a STC SMP: https://tests.stockfishchess.org/tests/view/662808133fe04ce4cefc667c closes https://github.com/official-stockfish/Stockfish/pull/5183 No functional change
This commit is contained in:
@@ -25,12 +25,14 @@
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
|
||||
#include "nnue/network.h"
|
||||
#include "nnue/nnue_misc.h"
|
||||
#include "position.h"
|
||||
#include "types.h"
|
||||
#include "uci.h"
|
||||
#include "nnue/nnue_accumulator.h"
|
||||
|
||||
namespace Stockfish {
|
||||
|
||||
@@ -45,7 +47,10 @@ int Eval::simple_eval(const Position& pos, Color c) {
|
||||
|
||||
// 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.
|
||||
Value Eval::evaluate(const Eval::NNUE::Networks& networks, const Position& pos, int optimism) {
|
||||
Value Eval::evaluate(const Eval::NNUE::Networks& networks,
|
||||
const Position& pos,
|
||||
Eval::NNUE::AccumulatorCaches& caches,
|
||||
int optimism) {
|
||||
|
||||
assert(!pos.checkers());
|
||||
|
||||
@@ -55,8 +60,8 @@ Value Eval::evaluate(const Eval::NNUE::Networks& networks, const Position& pos,
|
||||
int nnueComplexity;
|
||||
int v;
|
||||
|
||||
Value nnue = smallNet ? networks.small.evaluate(pos, true, &nnueComplexity, psqtOnly)
|
||||
: networks.big.evaluate(pos, true, &nnueComplexity, false);
|
||||
Value nnue = smallNet ? networks.small.evaluate(pos, nullptr, true, &nnueComplexity, psqtOnly)
|
||||
: networks.big.evaluate(pos, &caches.big, true, &nnueComplexity, false);
|
||||
|
||||
const auto adjustEval = [&](int optDiv, int nnueDiv, int npmDiv, int pawnCountConstant,
|
||||
int pawnCountMul, int npmConstant, int evalDiv,
|
||||
@@ -94,20 +99,22 @@ Value Eval::evaluate(const Eval::NNUE::Networks& networks, const Position& pos,
|
||||
// Trace scores are from white's point of view
|
||||
std::string Eval::trace(Position& pos, const Eval::NNUE::Networks& networks) {
|
||||
|
||||
auto caches = std::make_unique<Eval::NNUE::AccumulatorCaches>();
|
||||
|
||||
if (pos.checkers())
|
||||
return "Final evaluation: none (in check)";
|
||||
|
||||
std::stringstream ss;
|
||||
ss << std::showpoint << std::noshowpos << std::fixed << std::setprecision(2);
|
||||
ss << '\n' << NNUE::trace(pos, networks) << '\n';
|
||||
ss << '\n' << NNUE::trace(pos, networks, *caches) << '\n';
|
||||
|
||||
ss << std::showpoint << std::showpos << std::fixed << std::setprecision(2) << std::setw(15);
|
||||
|
||||
Value v = networks.big.evaluate(pos, false);
|
||||
Value v = networks.big.evaluate(pos, &caches->big, false);
|
||||
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, VALUE_ZERO);
|
||||
v = evaluate(networks, pos, *caches, VALUE_ZERO);
|
||||
v = pos.side_to_move() == WHITE ? v : -v;
|
||||
ss << "Final evaluation " << 0.01 * UCIEngine::to_cp(v, pos) << " (white side)";
|
||||
ss << " [with scaled NNUE, ...]";
|
||||
|
||||
Reference in New Issue
Block a user