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
+17 -14
View File
@@ -27,15 +27,15 @@
#include <cstdlib>
#include <initializer_list>
#include <iostream>
#include <utility>
#include <sstream>
#include <utility>
#include "evaluate.h"
#include "misc.h"
#include "movegen.h"
#include "movepick.h"
#include "nnue/evaluate_nnue.h"
#include "nnue/nnue_common.h"
#include "nnue/nnue_misc.h"
#include "position.h"
#include "syzygy/tbprobe.h"
#include "thread.h"
@@ -135,7 +135,8 @@ Search::Worker::Worker(SharedState& sharedState,
manager(std::move(sm)),
options(sharedState.options),
threads(sharedState.threads),
tt(sharedState.tt) {
tt(sharedState.tt),
networks(sharedState.networks) {
clear();
}
@@ -566,8 +567,9 @@ Value Search::Worker::search(
// Step 2. Check for aborted search and immediate draw
if (threads.stop.load(std::memory_order_relaxed) || pos.is_draw(ss->ply)
|| ss->ply >= MAX_PLY)
return (ss->ply >= MAX_PLY && !ss->inCheck) ? evaluate(pos, thisThread->optimism[us])
: value_draw(thisThread->nodes);
return (ss->ply >= MAX_PLY && !ss->inCheck)
? evaluate(networks, pos, thisThread->optimism[us])
: value_draw(thisThread->nodes);
// Step 3. Mate distance pruning. Even if we mate at the next move our score
// would be at best mate_in(ss->ply + 1), but if alpha is already bigger because
@@ -700,7 +702,7 @@ Value Search::Worker::search(
{
// Providing the hint that this node's accumulator will be used often
// brings significant Elo gain (~13 Elo).
Eval::NNUE::hint_common_parent_position(pos);
Eval::NNUE::hint_common_parent_position(pos, networks);
unadjustedStaticEval = eval = ss->staticEval;
}
else if (ss->ttHit)
@@ -708,9 +710,9 @@ Value Search::Worker::search(
// Never assume anything about values stored in TT
unadjustedStaticEval = tte->eval();
if (unadjustedStaticEval == VALUE_NONE)
unadjustedStaticEval = evaluate(pos, thisThread->optimism[us]);
unadjustedStaticEval = evaluate(networks, pos, thisThread->optimism[us]);
else if (PvNode)
Eval::NNUE::hint_common_parent_position(pos);
Eval::NNUE::hint_common_parent_position(pos, networks);
ss->staticEval = eval = to_corrected_static_eval(unadjustedStaticEval, *thisThread, pos);
@@ -720,7 +722,7 @@ Value Search::Worker::search(
}
else
{
unadjustedStaticEval = evaluate(pos, thisThread->optimism[us]);
unadjustedStaticEval = evaluate(networks, pos, thisThread->optimism[us]);
ss->staticEval = eval = to_corrected_static_eval(unadjustedStaticEval, *thisThread, pos);
// Static evaluation is saved as it was before adjustment by correction history
@@ -877,7 +879,7 @@ Value Search::Worker::search(
}
}
Eval::NNUE::hint_common_parent_position(pos);
Eval::NNUE::hint_common_parent_position(pos, networks);
}
moves_loop: // When in check, search starts here
@@ -1413,8 +1415,9 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta,
// Step 2. Check for an immediate draw or maximum ply reached
if (pos.is_draw(ss->ply) || ss->ply >= MAX_PLY)
return (ss->ply >= MAX_PLY && !ss->inCheck) ? evaluate(pos, thisThread->optimism[us])
: VALUE_DRAW;
return (ss->ply >= MAX_PLY && !ss->inCheck)
? evaluate(networks, pos, thisThread->optimism[us])
: VALUE_DRAW;
assert(0 <= ss->ply && ss->ply < MAX_PLY);
@@ -1445,7 +1448,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta,
// Never assume anything about values stored in TT
unadjustedStaticEval = tte->eval();
if (unadjustedStaticEval == VALUE_NONE)
unadjustedStaticEval = evaluate(pos, thisThread->optimism[us]);
unadjustedStaticEval = evaluate(networks, pos, thisThread->optimism[us]);
ss->staticEval = bestValue =
to_corrected_static_eval(unadjustedStaticEval, *thisThread, pos);
@@ -1458,7 +1461,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta,
{
// In case of null move search, use previous static eval with a different sign
unadjustedStaticEval = (ss - 1)->currentMove != Move::null()
? evaluate(pos, thisThread->optimism[us])
? evaluate(networks, pos, thisThread->optimism[us])
: -(ss - 1)->staticEval;
ss->staticEval = bestValue =
to_corrected_static_eval(unadjustedStaticEval, *thisThread, pos);