X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fnnue%2Fevaluate_nnue.cpp;h=eb6ad71f8d95cb86e5759066d026b183624432b0;hb=7f1333ccf89c715933ead72e31233510c6f4d146;hp=8828ae517e362f34422544c8667fed6e27d9945a;hpb=2e2865d34b6767e60ea55277bc6b1d642795ecc3;p=stockfish diff --git a/src/nnue/evaluate_nnue.cpp b/src/nnue/evaluate_nnue.cpp index 8828ae51..eb6ad71f 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-2021 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2022 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 @@ -109,7 +109,7 @@ namespace Stockfish::Eval::NNUE { { write_little_endian(stream, Version); write_little_endian(stream, hashValue); - write_little_endian(stream, desc.size()); + write_little_endian(stream, (std::uint32_t)desc.size()); stream.write(&desc[0], desc.size()); return !stream.fail(); } @@ -137,45 +137,38 @@ namespace Stockfish::Eval::NNUE { } // 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 = 10 - pos.non_pawn_material() / 1515; #if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN) TransformedFeatureType transformedFeaturesUnaligned[ FeatureTransformer::BufferSize + alignment / sizeof(TransformedFeatureType)]; - char bufferUnaligned[Network::BufferSize + alignment]; auto* transformedFeatures = align_ptr_up(&transformedFeaturesUnaligned[0]); - auto* buffer = align_ptr_up(&bufferUnaligned[0]); #else alignas(alignment) TransformedFeatureType transformedFeatures[FeatureTransformer::BufferSize]; - alignas(alignment) char buffer[Network::BufferSize]; #endif ASSERT_ALIGNED(transformedFeatures, alignment); - ASSERT_ALIGNED(buffer, alignment); - const std::size_t bucket = (pos.count() - 1) / 4; + const int bucket = (pos.count() - 1) / 4; const auto psqt = featureTransformer->transform(pos, transformedFeatures, bucket); - const auto output = network[bucket]->propagate(transformedFeatures, buffer); + const auto positional = network[bucket]->propagate(transformedFeatures); - int materialist = psqt; - int positional = output[0]; + if (complexity) + *complexity = abs(psqt - positional) / OutputScale; - int delta_npm = abs(pos.non_pawn_material(WHITE) - pos.non_pawn_material(BLACK)); - int entertainment = (adjusted && delta_npm <= BishopValueMg - KnightValueMg ? 7 : 0); - - int A = 128 - entertainment; - int B = 128 + entertainment; - - int sum = (A * materialist + B * positional) / 128; - - return static_cast( sum / 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)); + else + return static_cast((psqt + positional) / OutputScale); } struct NnueEvalTrace { @@ -196,27 +189,20 @@ namespace Stockfish::Eval::NNUE { #if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN) TransformedFeatureType transformedFeaturesUnaligned[ FeatureTransformer::BufferSize + alignment / sizeof(TransformedFeatureType)]; - char bufferUnaligned[Network::BufferSize + alignment]; auto* transformedFeatures = align_ptr_up(&transformedFeaturesUnaligned[0]); - auto* buffer = align_ptr_up(&bufferUnaligned[0]); #else alignas(alignment) TransformedFeatureType transformedFeatures[FeatureTransformer::BufferSize]; - alignas(alignment) char buffer[Network::BufferSize]; #endif ASSERT_ALIGNED(transformedFeatures, alignment); - ASSERT_ALIGNED(buffer, alignment); NnueEvalTrace t{}; t.correctBucket = (pos.count() - 1) / 4; - for (std::size_t bucket = 0; bucket < LayerStacks; ++bucket) { - const auto psqt = featureTransformer->transform(pos, transformedFeatures, bucket); - const auto output = network[bucket]->propagate(transformedFeatures, buffer); - - int materialist = psqt; - int positional = output[0]; + for (IndexType bucket = 0; bucket < LayerStacks; ++bucket) { + const auto materialist = featureTransformer->transform(pos, transformedFeatures, bucket); + const auto positional = network[bucket]->propagate(transformedFeatures); t.psqt[bucket] = static_cast( materialist / OutputScale ); t.positional[bucket] = static_cast( positional / OutputScale ); @@ -227,69 +213,46 @@ namespace Stockfish::Eval::NNUE { static const std::string PieceToChar(" PNBRQK pnbrqk"); - // Requires the buffer to have capacity for at least 5 values + + // format_cp_compact() converts a Value into (centi)pawns and writes it in a buffer. + // The buffer must have capacity for at least 5 chars. static void format_cp_compact(Value v, char* buffer) { buffer[0] = (v < 0 ? '-' : v > 0 ? '+' : ' '); int cp = std::abs(100 * v / PawnValueEg); - if (cp >= 10000) { - buffer[1] = '0' + cp / 10000; cp %= 10000; - buffer[2] = '0' + cp / 1000; cp %= 1000; - buffer[3] = '0' + cp / 100; cp %= 100; - buffer[4] = ' '; + buffer[1] = '0' + cp / 10000; cp %= 10000; + buffer[2] = '0' + cp / 1000; cp %= 1000; + buffer[3] = '0' + cp / 100; + buffer[4] = ' '; } else if (cp >= 1000) { - buffer[1] = '0' + cp / 1000; cp %= 1000; - buffer[2] = '0' + cp / 100; cp %= 100; - buffer[3] = '.'; - buffer[4] = '0' + cp / 10; + buffer[1] = '0' + cp / 1000; cp %= 1000; + buffer[2] = '0' + cp / 100; cp %= 100; + buffer[3] = '.'; + buffer[4] = '0' + cp / 10; } else { - buffer[1] = '0' + cp / 100; cp %= 100; - buffer[2] = '.'; - buffer[3] = '0' + cp / 10; cp %= 10; - buffer[4] = '0' + cp / 1; + buffer[1] = '0' + cp / 100; cp %= 100; + buffer[2] = '.'; + buffer[3] = '0' + cp / 10; cp %= 10; + buffer[4] = '0' + cp / 1; } } - // Requires the buffer to have capacity for at least 7 values + + // 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 ? '+' : ' '); - int cp = std::abs(100 * v / PawnValueEg); + buffer[0] = (v < 0 ? '-' : v > 0 ? '+' : ' '); - if (cp >= 10000) - { - buffer[1] = '0' + cp / 10000; cp %= 10000; - buffer[2] = '0' + cp / 1000; cp %= 1000; - buffer[3] = '0' + cp / 100; cp %= 100; - buffer[4] = '.'; - buffer[5] = '0' + cp / 10; cp %= 10; - buffer[6] = '0' + cp; - } - else if (cp >= 1000) - { - buffer[1] = ' '; - buffer[2] = '0' + cp / 1000; cp %= 1000; - buffer[3] = '0' + cp / 100; cp %= 100; - buffer[4] = '.'; - buffer[5] = '0' + cp / 10; cp %= 10; - buffer[6] = '0' + cp; - } - else - { - buffer[1] = ' '; - buffer[2] = ' '; - buffer[3] = '0' + cp / 100; cp %= 100; - buffer[4] = '.'; - buffer[5] = '0' + cp / 10; cp %= 10; - buffer[6] = '0' + cp / 1; - } + double cp = 1.0 * std::abs(int(v)) / PawnValueEg; + sprintf(&buffer[1], "%6.2f", cp); } @@ -419,7 +382,7 @@ namespace Stockfish::Eval::NNUE { actualFilename = filename.value(); else { - if (eval_file_loaded != EvalFileDefaultName) + if (currentEvalFileName != EvalFileDefaultName) { msg = "Failed to export a net. A non-embedded net can only be saved if the filename is specified";