Refactor Network Usage

Continuing from PR #4968, this update improves how Stockfish handles network
usage, making it easier to manage and modify networks in the future.

With the introduction of a dedicated Network class, creating networks has become
straightforward. See uci.cpp:
```cpp
NN::NetworkBig({EvalFileDefaultNameBig, "None", ""}, NN::embeddedNNUEBig)
```

The new `Network` encapsulates all network-related logic, significantly reducing
the complexity previously required to support multiple network types, such as
the distinction between small and big networks #4915.

Non-Regression STC:
https://tests.stockfishchess.org/tests/view/65edd26c0ec64f0526c43584
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 33760 W: 8887 L: 8661 D: 16212
Ptnml(0-2): 143, 3795, 8808, 3961, 173

Non-Regression SMP STC:
https://tests.stockfishchess.org/tests/view/65ed71970ec64f0526c42fdd
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 59088 W: 15121 L: 14931 D: 29036
Ptnml(0-2): 110, 6640, 15829, 6880, 85

Compiled with `make -j profile-build`
```
bash ./bench_parallel.sh ./stockfish ./stockfish-nnue 13 50

sf_base =  1568540 +/-   7637 (95%)
sf_test =  1573129 +/-   7301 (95%)
diff    =     4589 +/-   8720 (95%)
speedup = 0.29260% +/- 0.556% (95%)
```

Compiled with `make -j build`
```
bash ./bench_parallel.sh ./stockfish ./stockfish-nnue 13 50

sf_base =  1472653 +/-   7293 (95%)
sf_test =  1491928 +/-   7661 (95%)
diff    =    19275 +/-   7154 (95%)
speedup = 1.30886% +/- 0.486% (95%)
```

closes https://github.com/official-stockfish/Stockfish/pull/5100

No functional change
This commit is contained in:
Disservin
2024-03-09 14:42:37 +01:00
parent f072634e24
commit 1a26d698de
18 changed files with 948 additions and 826 deletions

View File

@@ -22,25 +22,25 @@
#include <cassert>
#include <cctype>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <memory>
#include <optional>
#include <sstream>
#include <vector>
#include <cstdint>
#include "benchmark.h"
#include "evaluate.h"
#include "movegen.h"
#include "nnue/evaluate_nnue.h"
#include "nnue/nnue_architecture.h"
#include "nnue/network.h"
#include "nnue/nnue_common.h"
#include "perft.h"
#include "position.h"
#include "search.h"
#include "syzygy/tbprobe.h"
#include "types.h"
#include "ucioption.h"
#include "perft.h"
namespace Stockfish {
@@ -48,17 +48,20 @@ constexpr auto StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKB
constexpr int NormalizeToPawnValue = 356;
constexpr int MaxHashMB = Is64Bit ? 33554432 : 2048;
namespace NN = Eval::NNUE;
UCI::UCI(int argc, char** argv) :
networks(NN::Networks(
NN::NetworkBig({EvalFileDefaultNameBig, "None", ""}, NN::embeddedNNUEBig),
NN::NetworkSmall({EvalFileDefaultNameSmall, "None", ""}, NN::embeddedNNUESmall))),
cli(argc, argv) {
evalFiles = {{Eval::NNUE::Big, {"EvalFile", EvalFileDefaultNameBig, "None", ""}},
{Eval::NNUE::Small, {"EvalFileSmall", EvalFileDefaultNameSmall, "None", ""}}};
options["Debug Log File"] << Option("", [](const Option& o) { start_logger(o); });
options["Threads"] << Option(1, 1, 1024, [this](const Option&) {
threads.set({options, threads, tt});
threads.set({options, threads, tt, networks});
});
options["Hash"] << Option(16, 1, MaxHashMB, [this](const Option& o) {
@@ -80,14 +83,17 @@ UCI::UCI(int argc, char** argv) :
options["SyzygyProbeDepth"] << Option(1, 1, 100);
options["Syzygy50MoveRule"] << Option(true);
options["SyzygyProbeLimit"] << Option(7, 0, 7);
options["EvalFile"] << Option(EvalFileDefaultNameBig, [this](const Option&) {
evalFiles = Eval::NNUE::load_networks(cli.binaryDirectory, options, evalFiles);
options["EvalFile"] << Option(EvalFileDefaultNameBig, [this](const Option& o) {
networks.big.load(cli.binaryDirectory, o);
});
options["EvalFileSmall"] << Option(EvalFileDefaultNameSmall, [this](const Option&) {
evalFiles = Eval::NNUE::load_networks(cli.binaryDirectory, options, evalFiles);
options["EvalFileSmall"] << Option(EvalFileDefaultNameSmall, [this](const Option& o) {
networks.small.load(cli.binaryDirectory, o);
});
threads.set({options, threads, tt});
networks.big.load(cli.binaryDirectory, options["EvalFile"]);
networks.small.load(cli.binaryDirectory, options["EvalFileSmall"]);
threads.set({options, threads, tt, networks});
search_clear(); // After threads are up
}
@@ -157,7 +163,7 @@ void UCI::loop() {
std::string f;
if (is >> std::skipws >> f)
filename = f;
Eval::NNUE::save_eval(filename, Eval::NNUE::Big, evalFiles);
networks.big.save(filename);
}
else if (token == "--help" || token == "help" || token == "--license" || token == "license")
sync_cout
@@ -218,7 +224,8 @@ void UCI::go(Position& pos, std::istringstream& is, StateListPtr& states) {
Search::LimitsType limits = parse_limits(pos, is);
Eval::NNUE::verify(options, evalFiles);
networks.big.verify(options["EvalFile"]);
networks.small.verify(options["EvalFileSmall"]);
if (limits.perft)
{
@@ -283,9 +290,11 @@ void UCI::trace_eval(Position& pos) {
Position p;
p.set(pos.fen(), options["UCI_Chess960"], &states->back());
Eval::NNUE::verify(options, evalFiles);
networks.big.verify(options["EvalFile"]);
networks.small.verify(options["EvalFileSmall"]);
sync_cout << "\n" << Eval::trace(p) << sync_endl;
sync_cout << "\n" << Eval::trace(p, networks) << sync_endl;
}
void UCI::search_clear() {