X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fnnue%2Fevaluate_nnue.cpp;h=a1a90023909f98f25826691d738ac838a33e551d;hb=af110e02ec96cdb46cf84c68252a1da15a902395;hp=9254e36f9ba9d7252bdf20e120980f24c5856e8e;hpb=5f781d366e0f4369ec12e36c9978ad63ffa32235;p=stockfish diff --git a/src/nnue/evaluate_nnue.cpp b/src/nnue/evaluate_nnue.cpp index 9254e36f..a1a90023 100644 --- a/src/nnue/evaluate_nnue.cpp +++ b/src/nnue/evaluate_nnue.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,15 +18,15 @@ // Code for calculating NNUE evaluation function +#include +#include #include #include #include -#include -#include +#include #include "../evaluate.h" #include "../position.h" -#include "../misc.h" #include "../uci.h" #include "../types.h" @@ -83,7 +83,7 @@ namespace Stockfish::Eval::NNUE { } // namespace Detail // Initialize the evaluation function parameters - void initialize() { + static void initialize() { Detail::initialize(featureTransformer); for (std::size_t i = 0; i < LayerStacks; ++i) @@ -91,7 +91,7 @@ namespace Stockfish::Eval::NNUE { } // Read network header - bool read_header(std::istream& stream, std::uint32_t* hashValue, std::string* desc) + static bool read_header(std::istream& stream, std::uint32_t* hashValue, std::string* desc) { std::uint32_t version, size; @@ -105,7 +105,7 @@ namespace Stockfish::Eval::NNUE { } // Write network header - bool write_header(std::ostream& stream, std::uint32_t hashValue, const std::string& desc) + static bool write_header(std::ostream& stream, std::uint32_t hashValue, const std::string& desc) { write_little_endian(stream, Version); write_little_endian(stream, hashValue); @@ -115,7 +115,7 @@ namespace Stockfish::Eval::NNUE { } // Read network parameters - bool read_parameters(std::istream& stream) { + static bool read_parameters(std::istream& stream) { std::uint32_t hashValue; if (!read_header(stream, &hashValue, &netDescription)) return false; @@ -127,7 +127,7 @@ namespace Stockfish::Eval::NNUE { } // Write network parameters - bool write_parameters(std::ostream& stream) { + static bool write_parameters(std::ostream& stream) { if (!write_header(stream, HashValue, netDescription)) return false; if (!Detail::write_parameters(stream, *featureTransformer)) return false; @@ -136,14 +136,18 @@ namespace Stockfish::Eval::NNUE { return (bool)stream; } + void hint_common_parent_position(const Position& pos) { + featureTransformer->hint_common_access(pos); + } + // Evaluation function. Perform differential calculation. - Value evaluate(const Position& pos, bool adjusted) { + Value evaluate(const Position& pos, bool adjusted, int* complexity) { // 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; - int delta = 7; + constexpr int delta = 24; #if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN) TransformedFeatureType transformedFeaturesUnaligned[ @@ -161,9 +165,12 @@ namespace Stockfish::Eval::NNUE { const auto psqt = featureTransformer->transform(pos, transformedFeatures, bucket); const auto positional = network[bucket]->propagate(transformedFeatures); + if (complexity) + *complexity = abs(psqt - positional) / OutputScale; + // Give more value to positional evaluation when adjusted flag is set if (adjusted) - return static_cast(((128 - delta) * psqt + (128 + delta) * positional) / 128 / OutputScale); + return static_cast(((1024 - delta) * psqt + (1024 + delta) * positional) / (1024 * OutputScale)); else return static_cast((psqt + positional) / OutputScale); } @@ -208,7 +215,7 @@ namespace Stockfish::Eval::NNUE { return t; } - static const std::string PieceToChar(" PNBRQK pnbrqk"); + constexpr std::string_view PieceToChar(" PNBRQK pnbrqk"); // format_cp_compact() converts a Value into (centi)pawns and writes it in a buffer. @@ -217,7 +224,7 @@ namespace Stockfish::Eval::NNUE { buffer[0] = (v < 0 ? '-' : v > 0 ? '+' : ' '); - int cp = std::abs(100 * v / PawnValueEg); + int cp = std::abs(100 * v / UCI::NormalizeToPawnValue); if (cp >= 10000) { buffer[1] = '0' + cp / 10000; cp %= 10000; @@ -242,14 +249,15 @@ namespace Stockfish::Eval::NNUE { } - // format_cp_aligned_dot() converts a Value into (centi)pawns and writes it in a buffer, - // always keeping two decimals. The buffer must have capacity for at least 7 chars. - static void format_cp_aligned_dot(Value v, char* buffer) { - - buffer[0] = (v < 0 ? '-' : v > 0 ? '+' : ' '); + // format_cp_aligned_dot() converts a Value into (centi)pawns, always keeping two decimals. + static void format_cp_aligned_dot(Value v, std::stringstream &stream) { + const double cp = 1.0 * std::abs(int(v)) / UCI::NormalizeToPawnValue; - double cp = 1.0 * std::abs(int(v)) / PawnValueEg; - sprintf(&buffer[1], "%6.2f", cp); + stream << (v < 0 ? '-' : v > 0 ? '+' : ' ') + << std::setiosflags(std::ios::fixed) + << std::setw(6) + << std::setprecision(2) + << cp; } @@ -329,17 +337,10 @@ namespace Stockfish::Eval::NNUE { for (std::size_t bucket = 0; bucket < LayerStacks; ++bucket) { - char buffer[3][8]; - std::memset(buffer, '\0', sizeof(buffer)); - - format_cp_aligned_dot(t.psqt[bucket], buffer[0]); - format_cp_aligned_dot(t.positional[bucket], buffer[1]); - format_cp_aligned_dot(t.psqt[bucket] + t.positional[bucket], buffer[2]); - - ss << "| " << bucket << " " - << " | " << buffer[0] << " " - << " | " << buffer[1] << " " - << " | " << buffer[2] << " " + ss << "| " << bucket << " "; + ss << " | "; format_cp_aligned_dot(t.psqt[bucket], ss); ss << " " + << " | "; format_cp_aligned_dot(t.positional[bucket], ss); ss << " " + << " | "; format_cp_aligned_dot(t.psqt[bucket] + t.positional[bucket], ss); ss << " " << " |"; if (bucket == t.correctBucket) ss << " <-- this bucket is used";