diff options
| author | Scott Gasch <[email protected]> | 2026-10-20 18:37:20 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-10-20 18:37:20 -0700 |
| commit | 9cf14e14e6999420f234cda951894337e034f57c (patch) | |
| tree | d4845d0cf127ef4226a5cd2e60472ee750213614 /src/chess.h | |
| parent | c8c6bbc2c1a103e5b07b079a0f8bdf66c7724d80 (diff) | |
NNUE: re-fit raw-to-score calibration, NNU4 weight format, super-lazy default-on, lazy probe measured net-negative
Fits an affine (a + b*raw) correction into every exported .nnue file
(export_nnue_weights.py's CalibrateScoreMapping) so the engine's
consumed centipawn output tracks Stockfish's real score scale rather
than the net's nominal raw WDL-sigmoid output -- training variance
alone shifts this mapping across retrains even with an identical
recipe, so it's re-fit and baked in per export rather than assumed
constant. Weight format bumped to "NNU4" to carry the two new floats;
older NNU1/2/3 files are no longer readable.
Super-lazy (material-only) pre-filter promoted to default-on
(g_fUseNnueSuperLazy = TRUE) with a recalibrated per-material-bucket
margin table (measured against the recalibrated net, 16-shard
cross_sectional_200k.ep_ sample) -- real, measured nps win across all
three curated suites. The separate lazy-probe gate (accumulator-based
early exit) is measured net-negative on real search traffic at this
net's probe-vs-forward latency ratio and stays off by default
(g_fUseNnueLazyProbe = FALSE); code kept live since margin tuning
could still flip this, per docs/NNUE.md.
Also: direct per-call latency instrumentation for NnueProbeScore/
NnueForward (root.c, EVAL_TIME build) to make the lazy-probe
breakeven math measurable directly instead of inferred; QSearch
futility margins given real-data-derived NNUE_FULL/NNUE_LAZY
starting points.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Diffstat (limited to 'src/chess.h')
| -rwxr-xr-x | src/chess.h | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/src/chess.h b/src/chess.h index 3e65e7f..34099b2 100755 --- a/src/chess.h +++ b/src/chess.h @@ -1431,6 +1431,25 @@ typedef struct _COUNTERS UINT64 u64CyclesSuperLazyExit; UINT64 u64CyclesLazyExit; UINT64 u64CyclesFullEvalExit; + + // 2026-10-20: direct per-call latency of the two NNUE eval + // primitives (nnueeval.c), as opposed to the HCE-oriented + // whole-path-cost counters above (which NNUE's Eval() branch + // doesn't feed -- it's gated on g_fUseNnueEval at runtime, not + // #ifdef LAZY_EVAL). u64CyclesNnueProbeCall/u64CyclesNnueForwardCall + // time just the TIMED_EVAL_CALL-wrapped NnueProbeScore()/ + // NnueForward() calls themselves (eval.c's production NNUE + // branch); u64NnueProbeAttempts counts every probe call made + // (hit or miss) -- unlike u64LazyEvals, which only counts + // hits -- needed as the denominator for a true avg-cost-per- + // attempt (the question that actually matters for judging + // whether the gate pays for itself: cost is paid on every + // attempt, the saving only on a hit). u64FullEvals already + // counts NnueForward calls 1:1 on this path, so no separate + // attempt counter is needed for it. + UINT64 u64CyclesNnueProbeCall; + UINT64 u64CyclesNnueForwardCall; + UINT64 u64NnueProbeAttempts; } tree; @@ -2378,6 +2397,12 @@ extern CHAR g_rgfNnueFc3Weight[NNUE_L3]; extern float g_rgfNnueFc3Bias; extern float g_rgfNnueActScale[3]; extern float g_rgfNnueWeightScale[3]; +// Affine raw-to-real-score correction (a + b*raw), re-fit and baked +// into every export by CalibrateScoreMapping -- see nnueeval.c's +// declaration comment and the 2026-10-20 "keeping this stable across +// retrains" conversation. Defaults (0,1) are the identity transform. +extern float g_fNnueCalibA; +extern float g_fNnueCalibB; extern FLAG g_fNnueWeightsLoaded; extern FLAG g_fUseNnueEval; |
