mirror of
https://github.com/official-stockfish/Stockfish.git
synced 2026-07-23 05:07:14 +00:00
S人ving Privàte Ryän
Fixes problems with non-ASCII characters in paths. Fixes #3424. Changes - Bump the minimum supported Clang version to 11 to support std::filesystem - Use std::optional for empty values instead of string sentinels like "None" - Remove the FixedString class - Move the EvalFile network path from the network struct to the engine - Simplify parts of the command-line handling - Remove the old dual-net logic from export_net - And ofc we now support non-ascii paths for windows Behavior Change - Because the EvalFile is no longer part of the network, it won't be included in the hashing, thus the network sharing is no longer dependent on the EvalFile path - As a result, if the binary version and network are the same, changing only the EvalFile location will now reuse the same shared network This also fixes a master bug where: ``` export_net None setoption name EvalFile value None export_net None Failed to export a net ``` would fail on the second export. With this patch, the second export succeeds. Quick Fishtest Check that nets load like normal. https://tests.stockfishchess.org/tests/view/6a455593f97ff95f787954da <img width="833" height="1137" alt="image" src="https://github.com/user-attachments/assets/fffee63b-c63a-4d5e-b13d-87d58bc28c88" /> closes https://github.com/official-stockfish/Stockfish/pull/6937 No functional change Co-authored-by: anematode <timothy.herchen@gmail.com>
This commit is contained in:
committed by
Joost VandeVondele
co-authored by
anematode
parent
d5bbc6b67d
commit
22548cb0c0
+45
-49
@@ -24,6 +24,7 @@
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
|
||||
#define INCBIN_SILENCE_BITCODE_WARNING
|
||||
#include "../incbin/incbin.h"
|
||||
@@ -58,8 +59,10 @@ const unsigned char gEmbeddedNNUEData[1] = {0x0};
|
||||
const unsigned int gEmbeddedNNUESize = 1;
|
||||
#endif
|
||||
|
||||
|
||||
namespace Stockfish::Eval::NNUE {
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace Detail {
|
||||
|
||||
@@ -84,60 +87,56 @@ bool write_parameters(std::ostream& stream, const T& reference) {
|
||||
|
||||
} // namespace Detail
|
||||
|
||||
void Network::load(const std::string& rootDirectory, std::string evalfilePath) {
|
||||
void Network::load(const fs::path& rootDirectory, fs::path evalfilePath, EvalFile& evalFile) {
|
||||
#if defined(DEFAULT_NNUE_DIRECTORY)
|
||||
std::vector<std::string> dirs = {"<internal>", "", rootDirectory,
|
||||
stringify(DEFAULT_NNUE_DIRECTORY)};
|
||||
std::vector<fs::path> dirs = {fs::path{}, rootDirectory,
|
||||
fs::path(stringify(DEFAULT_NNUE_DIRECTORY))};
|
||||
#else
|
||||
std::vector<std::string> dirs = {"<internal>", "", rootDirectory};
|
||||
std::vector<fs::path> dirs = {fs::path{}, rootDirectory};
|
||||
#endif
|
||||
|
||||
if (evalfilePath.empty())
|
||||
evalfilePath = evalFile.defaultName;
|
||||
|
||||
if (evalFile.current != evalfilePath && evalfilePath == evalFile.defaultName)
|
||||
load_internal(evalFile);
|
||||
|
||||
for (const auto& directory : dirs)
|
||||
{
|
||||
if (std::string(evalFile.current) != evalfilePath)
|
||||
{
|
||||
if (directory != "<internal>")
|
||||
load_user_net(directory, evalfilePath);
|
||||
else if (evalfilePath == std::string(evalFile.defaultName))
|
||||
load_internal();
|
||||
}
|
||||
if (evalFile.current != evalfilePath)
|
||||
load_external(directory, evalfilePath, evalFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Network::save(const std::optional<std::string>& filename) const {
|
||||
std::string actualFilename;
|
||||
std::string msg;
|
||||
|
||||
if (filename.has_value())
|
||||
actualFilename = filename.value();
|
||||
else
|
||||
bool Network::save(const EvalFile& evalFile, const std::optional<fs::path>& filename) const {
|
||||
if (!evalFile.current.has_value())
|
||||
{
|
||||
if (std::string(evalFile.current) != std::string(evalFile.defaultName))
|
||||
{
|
||||
msg = "Failed to export a net. "
|
||||
"A non-embedded net can only be saved if the filename is specified";
|
||||
|
||||
sync_cout << msg << sync_endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
actualFilename = evalFile.defaultName;
|
||||
sync_cout << "Failed to export a net. No network file is currently loaded. "
|
||||
"Please load a network file first."
|
||||
<< sync_endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!filename.has_value() && evalFile.current != evalFile.defaultName)
|
||||
{
|
||||
sync_cout << "Failed to export a net. A non-embedded net can only be "
|
||||
"saved if the filename is specified"
|
||||
<< sync_endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
fs::path actualFilename = filename.value_or(evalFile.defaultName);
|
||||
std::ofstream stream(actualFilename, std::ios_base::binary);
|
||||
bool saved = save(stream, evalFile.current, evalFile.netDescription);
|
||||
|
||||
msg = saved ? "Network saved successfully to " + actualFilename : "Failed to export a net";
|
||||
bool saved = save(stream, evalFile.netDescription);
|
||||
|
||||
sync_cout << (saved ? "Network saved successfully to " + actualFilename.string()
|
||||
: "Failed to export a net")
|
||||
<< sync_endl;
|
||||
|
||||
sync_cout << msg << sync_endl;
|
||||
return saved;
|
||||
}
|
||||
|
||||
|
||||
NetworkOutput Network::evaluate(const Position& pos,
|
||||
AccumulatorStack& accumulatorStack,
|
||||
AccumulatorCaches& cache) const {
|
||||
@@ -158,18 +157,20 @@ NetworkOutput Network::evaluate(const Position& pos,
|
||||
}
|
||||
|
||||
|
||||
void Network::verify(std::string evalfilePath,
|
||||
const std::function<void(std::string_view)>& f) const {
|
||||
void Network::verify(const std::function<void(std::string_view)>& f,
|
||||
const EvalFile& evalFile,
|
||||
fs::path evalfilePath) const {
|
||||
if (evalfilePath.empty())
|
||||
evalfilePath = evalFile.defaultName;
|
||||
|
||||
if (std::string(evalFile.current) != evalfilePath)
|
||||
if (evalFile.current != evalfilePath)
|
||||
{
|
||||
if (f)
|
||||
{
|
||||
std::string msg1 =
|
||||
"Network evaluation parameters compatible with the engine must be available.";
|
||||
std::string msg2 = "The network file " + evalfilePath + " was not loaded successfully.";
|
||||
std::string msg2 =
|
||||
"The network file " + evalfilePath.string() + " was not loaded successfully.";
|
||||
std::string msg3 = "The UCI option EvalFile might need to specify the full path, "
|
||||
"including the directory name, to the network file.";
|
||||
std::string msg4 = "The default net can be downloaded from: "
|
||||
@@ -189,8 +190,9 @@ void Network::verify(std::string evalfilePath,
|
||||
if (f)
|
||||
{
|
||||
usize size = sizeof(featureTransformer) + sizeof(NetworkArchitecture) * LayerStacks;
|
||||
f("NNUE evaluation using " + evalfilePath + " (" + std::to_string(size / (1024 * 1024))
|
||||
+ "MiB, (" + std::to_string(featureTransformer.InputDimensions) + ", "
|
||||
f("NNUE evaluation using " + evalfilePath.string() + " ("
|
||||
+ std::to_string(size / (1024 * 1024)) + "MiB, ("
|
||||
+ std::to_string(featureTransformer.InputDimensions) + ", "
|
||||
+ std::to_string(network[0].TransformedFeatureDimensions) + ", "
|
||||
+ std::to_string(network[0].FC_0_OUTPUTS) + ", " + std::to_string(network[0].FC_1_OUTPUTS)
|
||||
+ ", 1))");
|
||||
@@ -225,8 +227,8 @@ NnueEvalTrace Network::trace_evaluate(const Position& pos,
|
||||
}
|
||||
|
||||
|
||||
void Network::load_user_net(const std::string& dir, const std::string& evalfilePath) {
|
||||
std::ifstream stream(dir + evalfilePath, std::ios::binary);
|
||||
void Network::load_external(const fs::path& dir, const fs::path& evalfilePath, EvalFile& evalFile) {
|
||||
std::ifstream stream(dir / evalfilePath, std::ios::binary);
|
||||
auto description = load(stream);
|
||||
|
||||
if (description.has_value())
|
||||
@@ -237,7 +239,7 @@ void Network::load_user_net(const std::string& dir, const std::string& evalfileP
|
||||
}
|
||||
|
||||
|
||||
void Network::load_internal() {
|
||||
void Network::load_internal(EvalFile& evalFile) {
|
||||
// C++ way to prepare a buffer for a memory stream
|
||||
class MemoryBuffer: public std::basic_streambuf<char> {
|
||||
public:
|
||||
@@ -269,12 +271,7 @@ void Network::load_internal() {
|
||||
void Network::initialize() { initialized = true; }
|
||||
|
||||
|
||||
bool Network::save(std::ostream& stream,
|
||||
const std::string& name,
|
||||
const std::string& netDescription) const {
|
||||
if (name.empty() || name == "None")
|
||||
return false;
|
||||
|
||||
bool Network::save(std::ostream& stream, const std::string& netDescription) const {
|
||||
return write_parameters(stream, netDescription);
|
||||
}
|
||||
|
||||
@@ -295,7 +292,6 @@ usize Network::get_content_hash() const {
|
||||
hash_combine(h, featureTransformer);
|
||||
for (auto&& layerstack : network)
|
||||
hash_combine(h, layerstack);
|
||||
hash_combine(h, evalFile);
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user