diff options
| author | Scott Gasch <[email protected]> | 2026-10-15 16:26:09 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-10-15 16:26:09 -0700 |
| commit | 1ea81bae240912efb8cebabae35fe58bc5d12afb (patch) | |
| tree | e43b3bbb179601595a47f7c5c4661a297a8b4664 /src/chess.h | |
| parent | 3d55dc94497661b1577109b42a94cc3dba1860fb (diff) | |
Wire NNUE eval into real search path; fix critical perf regression
Load-and-call infra: export_nnue_weights.py-produced weight files can
now be loaded at runtime (nnueeval.c's NnueLoadWeights, "nnue load"
command, --nnueweights CLI flag for scripted match-play), and the FC
head (NnueForward) runs the real forward pass against the live
accumulator.
Real integration: Eval() now short-circuits to NnueForward when
g_fUseNnueEval && g_fNnueWeightsLoaded, so ./typhoon can actually play
on the NNUE eval -- ./eval_tune/test_vs_head.sh works unmodified to
compare it against the old HCE. ReInitializeSearcherContext (root.c)
gained a defensive accumulator recompute hook covering setboard's
downstream effect on the next go/ponder; it only fires when both
kings are validly placed, since testrecogn.c's synthetic positions
don't always have one at the moment this is called.
Critical fix: the NNUE accumulator maintenance added to move.c's 8
primitives (and MakeMove/UnmakeMove's king-move backup/restore) was
running unconditionally, on the mistaken assumption this was cheap.
It cost ~50% of engine throughput even with NNUE off (673k nps
measured vs the expected 1.4-1.5M baseline). Gated all of it behind
g_fUseNnueEval; classic HCE is back to ~1.52M nps, NNUE eval runs at
a fair ~409k nps (expected for an unquantized float32 forward pass).
This gating also exposed that testnnue.c's TestNnueAccumulator never
set g_fUseNnueEval, so its own direct NnueAccumRecompute calls raced
ahead of now-gated-off incremental maintenance; fixed by having the
test set/restore the flag around its run.
board.c: added en passant legality check to IsBoardLegal (rank vs
side-to-move, origin-square occupancy) -- a real, previously-latent
bug surfaced while building the NNUE test fixtures, unrelated to
NNUE itself.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Diffstat (limited to 'src/chess.h')
| -rwxr-xr-x | src/chess.h | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/src/chess.h b/src/chess.h index 1f67df1..cfe1d4e 100755 --- a/src/chess.h +++ b/src/chess.h @@ -205,8 +205,7 @@ typedef struct _DLIST_ENTRY // // Program version number // -#define VERSION "1.00" -#define REVISION "$Id: chess.h 354 2008-06-30 05:10:08Z scott $\n" +#define VERSION "2.00" // GIT_COMMIT is normally injected by GNUmakefile via -DGIT_COMMIT (short // hash, plus a -dirty suffix if the tree had uncommitted changes at build @@ -1641,6 +1640,8 @@ MOVE_SCORING_SCHEME; // weights exist -- not something to conflate with debugging the // harder plumbing now. #define NNUE_ACCUMULATOR_SIZE (256) // L1, nnue_model.py +#define NNUE_L2 (32) // nnue_model.py's L2 +#define NNUE_L3 (32) // nnue_model.py's L3 typedef struct _NNUE_ACCUMULATOR { @@ -2325,6 +2326,31 @@ NnueAccumRemoveFeature(NNUE_ACCUMULATOR *pAccum, ULONG uPerspective, void NnueAccumRecompute(NNUE_ACCUMULATOR *pAccum, POSITION *pos, ULONG uPerspective); +// +// FC head weights (nnueeval.c) -- the dense 2*L1 -> L2 -> L3 -> 1 +// layers that sit on top of the two accumulator halves. Still a +// placeholder (zero-initialized) until NnueLoadWeights successfully +// reads a real exported checkpoint (annotate_pgns/ +// export_nnue_weights.py's output format). g_fNnueWeightsLoaded is +// FALSE until that happens -- NnueForward does not check it itself +// (callers should, before trusting its output for anything beyond +// plumbing validation). +// +extern float g_rgfNnueFc1Weight[NNUE_L2][2 * NNUE_ACCUMULATOR_SIZE]; +extern float g_rgfNnueFc1Bias[NNUE_L2]; +extern float g_rgfNnueFc2Weight[NNUE_L3][NNUE_L2]; +extern float g_rgfNnueFc2Bias[NNUE_L3]; +extern float g_rgfNnueFc3Weight[NNUE_L3]; +extern float g_rgfNnueFc3Bias; +extern FLAG g_fNnueWeightsLoaded; +extern FLAG g_fUseNnueEval; + +FLAG +NnueLoadWeights(CHAR *szFilename); + +SCORE +NnueForward(SEARCHER_THREAD_CONTEXT *ctx); + #ifdef PERF_COUNTERS #define INC(x) ((x) += 1) #else |
