diff options
Diffstat (limited to 'src/chess.h')
| -rwxr-xr-x | src/chess.h | 161 |
1 files changed, 111 insertions, 50 deletions
diff --git a/src/chess.h b/src/chess.h index 702defb..78c0f94 100755 --- a/src/chess.h +++ b/src/chess.h @@ -941,19 +941,9 @@ typedef struct _COUNTERS UINT64 u64AvoidNullSuccess; UINT64 u64AvoidNullFailures; #endif - UINT64 u64EvalHashHits; UINT64 u64LazyEvals; - UINT64 u64FullEvals; - // Placeholder counters for root.c's per-tier eval-exit - // reporting -- eval.c's super-lazy exit itself hasn't been - // re-applied yet (see stash), so these always read 0 for now; - // that's accurate, not a stub bug, since no super-lazy exit - // exists in this build to increment them. UINT64 u64SuperLazyEvals; - UINT64 u64CyclesSuperLazyExit; - UINT64 u64CyclesLazyExit; - UINT64 u64CyclesFullEvalExit; - UINT64 u64CyclesEvalSuperLazy; + UINT64 u64FullEvals; UINT64 u64CyclesInEval; // @@ -1021,6 +1011,30 @@ typedef struct _COUNTERS UINT64 u64CyclesEvalLazyDecision; UINT64 u64CyclesEvalCountKingSafetyDefects; UINT64 u64CyclesEvalFileStormDefects; + + // + // 2026-09-07: the super-lazy exit (eval.c, before the regular + // LAZY_EVAL block) is a much cheaper material-only check than + // the regular lazy decision, so it gets its own cycle counter + // rather than folding into u64CyclesEvalLazyDecision -- a hit + // here never reaches the regular lazy-decision code at all. + // + UINT64 u64CyclesEvalSuperLazy; + + // Per-exit-path *total call cost*, i.e. the full entry-to-exit + // elapsed time for a call that left via that path -- not to be + // confused with the sub-timers above, which measure a single + // segment's cost regardless of how the call eventually exited. + // These three are mutually exclusive by construction (each + // Eval() call adds to exactly one) and sum to u64CyclesInEval, + // so u64CyclesInEval / (u64SuperLazyEvals + u64LazyEvals + + // u64FullEvals) is a real overall average, and each bucket + // divided by its own matching count (u64SuperLazyEvals, + // u64LazyEvals, u64FullEvals) gives a clean per-path average -- + // see root.c's eval-exit-breakdown report. + UINT64 u64CyclesSuperLazyExit; + UINT64 u64CyclesLazyExit; + UINT64 u64CyclesFullEvalExit; } tree; @@ -1241,6 +1255,24 @@ typedef struct _SEARCHER_THREAD_CONTEXT // called on. FLAG fCalibrateCandidate; #endif + // Which Eval() exit tier supplied the piPositional value most + // recently returned to this thread -- set inside Eval() itself + // (all three exit points), read right after the Eval() call in + // QSearch. Was CALIBRATE_QSEARCH_FUTILITY-only; promoted to + // unconditional 2026-09-08 since QSearch's real futility margin + // now indexes FUTILITY_BASE_MARGIN_BY_SOURCE with it, not just + // the calibration harness. See EVAL_POSITIONAL_SOURCE_* below. + ULONG uLastPositionalSource; +#ifdef CALIBRATE_QSEARCH_FUTILITY + // TRUE for the duration of a diagnostic "what if we hadn't pruned + // this move" re-search -- search.c's qsearch futility gate checks + // this and forces iFutility wide open so the diagnostic subtree + // itself isn't contaminated by the same pruning being measured. + // Never set recursively: a rejection can't occur while this is + // already TRUE (iFutility being wide open means nothing gets + // rejected), so there's no risk of runaway nested diagnosis. + FLAG fDiagUnprunedSubtree; +#endif CHAR szLastPV[SMALL_STRING_LEN_CHAR]; } SEARCHER_THREAD_CONTEXT; @@ -2820,14 +2852,27 @@ IsDraw(SEARCHER_THREAD_CONTEXT *ctx); // search.c // #define QPLIES_OF_NON_CAPTURE_CHECKS (2) -#define FUTILITY_BASE_MARGIN (50) -// Compatibility aliases for root.c/main.c's per-tier reporting, which -// expects these three names -- search.c hasn't been split into -// per-tier margins yet (still one flat FUTILITY_BASE_MARGIN), so all -// three alias the same value until that split is re-applied. -#define FUTILITY_BASE_MARGIN_FULL FUTILITY_BASE_MARGIN -#define FUTILITY_BASE_MARGIN_LAZY FUTILITY_BASE_MARGIN -#define FUTILITY_BASE_MARGIN_SUPERLAZY FUTILITY_BASE_MARGIN + +// Which Eval() exit tier supplied a given piPositional value -- +// SEARCHER_THREAD_CONTEXT.uLastPositionalSource above. Was diagnostic- +// only (CALIBRATE_QSEARCH_FUTILITY); promoted to unconditional +// 2026-09-08 once FUTILITY_BASE_MARGIN_BY_SOURCE (search.c) made it +// load-bearing for real search behavior, not just measurement. +#define EVAL_POSITIONAL_SOURCE_FULL (0) +#define EVAL_POSITIONAL_SOURCE_LAZY (1) +#define EVAL_POSITIONAL_SOURCE_SUPERLAZY (2) +#define EVAL_POSITIONAL_SOURCE_COUNT (3) + +// Per-tier qsearch futility base margins -- see search.c's +// FUTILITY_BASE_MARGIN_BY_SOURCE for the full derivation. Named here +// (rather than only as array entries in search.c) so eval.c's +// piPositional floor -- which only ever applies on the full-eval +// exit -- can reference the matching tier's constant directly instead +// of a stale flat value. +#define FUTILITY_BASE_MARGIN_FULL (450) +#define FUTILITY_BASE_MARGIN_LAZY (225) +#define FUTILITY_BASE_MARGIN_SUPERLAZY (275) + // Measured: disabling this entirely (see lmr_testing/RESULTS.md) is a // clear net loss across ringers/confident_quick/hard_quick, so IID itself // is load-bearing. The "is the top move crappy" gate in search.c's DO_IID @@ -3144,7 +3189,7 @@ PawnHashLookup(SEARCHER_THREAD_CONTEXT *ctx); // #define LAZY_EVAL #define LAZE_EVAL_BASE_SCORE 10 -#define LAZY_EVAL_BASE_MARGIN (75) // cheap material-only lazy exit margin; +#define LAZY_EVAL_BASE_MARGIN (75) // cheap material-only lazy exit margin; // widened by EstimatePositionalScore // if this isn't enough on its own // board_representation/EVAL.md section 9 (2026-09-06): below this @@ -3162,13 +3207,6 @@ PawnHashLookup(SEARCHER_THREAD_CONTEXT *ctx); extern const int g_iAhead[2]; extern const int g_iBehind[2]; -// No-op placeholder: eval.c's ROOK_FULL_HALF_OPEN_BONUS static cache -// (the thing InitEval() is meant to (re)build, called at startup and -// after every DNA reload) hasn't been re-applied yet -- see stash. -// Nothing to initialize until that cache exists. -void -InitEval(void); - ULONG DNABufferSizeBytes(); @@ -3184,14 +3222,15 @@ ImportEvalDNA(char *p); FLAG ReadEvalDNA(char *szFilename); - +void +InitEval(); SCORE -Eval(SEARCHER_THREAD_CONTEXT *, SCORE, SCORE, SCORE *); +Eval(SEARCHER_THREAD_CONTEXT *, SCORE, SCORE, SCORE (*)[2]); FLAG _EvalPasserRacesAgainstLoneKings(POSITION *, - PAWN_HASH_ENTRY *); + PAWN_HASH_ENTRY *); ULONG CountKingSafetyDefects(POSITION *pos, @@ -3212,6 +3251,22 @@ void DumpMarginSafetyCalibration(void); #endif +#ifdef CALIBRATE_QSEARCH_FUTILITY +// Which futility gate in _ShouldWeConsiderThisMove rejected a move -- +// see search.c's _QFutRecordSample. The recapture gate (used to be +// QFUT_GATE_RECAPTURE) was retired 2026-09-08 along with the +100 +// recapture bonus itself -- see the "recapture-shaped" comment in +// _ShouldWeConsiderThisMove for why (fRecaptureShaped never checked +// mv.cTo == mvLast.cTo, so it wasn't testing real recaptures). +#define QFUT_GATE_GENERIC_CAPTURE (0) +#define QFUT_GATE_CHECK_ROOK (1) +#define QFUT_GATE_CHECK_BISHOP (2) +#define QFUT_GATE_COUNT (3) + +void +DumpQSearchFutilityCalibration(void); +#endif + // // testeval.c // @@ -3352,22 +3407,13 @@ ParallelCompareUlong(ULONG uComparand, void *pComparators); ULONG CDECL ParallelCompareVector(void *pComparand, void *pComparators); -void CDECL -GetAttacks(SEE_LIST *pList, - POSITION *pos, - COOR cSquare, - ULONG uSide); - -void CDECL -SlowGetAttacks(SEE_LIST *pList, - POSITION *pos, - COOR cSquare, - ULONG uSide); - -// board_representation/MIGRATION.md section 3: bbPieces/bbPawns-backed -// GetAttacks primitive, verified correct (20,000-position sweep) and -// faster than asm GetAttacks (0.53-0.89x cycles/call across -// opening/middlegame/endgame -- see section 3's benchmark writeup). +// board_representation/MIGRATION.md sections 3/6/7: bbPieces/bbPawns- +// backed GetAttacks primitive. Verified correct (20,000-position +// sweep) and faster than the old mailbox implementation (0.53-0.89x +// cycles/call across opening/middlegame/endgame). Now the only +// GetAttacks implementation -- the old asm/CROUTINES mailbox versions +// (SlowGetAttacks, asm GetAttacks) were retired 2026-09-06 once all of +// section 7's retirement criteria cleared. void CDECL _GetAttacksBB(SEE_LIST *pList, POSITION *pos, @@ -3386,10 +3432,9 @@ _WhoAttacksSquareBB(POSITION *pos, BITBOARD bbOccupied); // _GetAttacksBB is the only implementation as of 2026-09-06 (see -// MIGRATION.md section 6) -- verified correct and faster than the old -// asm/CROUTINES mailbox versions (SlowGetAttacks, asm GetAttacks), -// which have been retired. Every call site written against the name -// "GetAttacks" didn't need touching when the default changed. +// MIGRATION.md section 7) -- this macro exists only so call sites +// written against the name "GetAttacks" didn't need touching when the +// old asm/CROUTINES mailbox versions were retired. #define GetAttacks _GetAttacksBB #ifdef _X86_ @@ -3596,6 +3641,12 @@ COMMAND(BenchCommand); void TestDraw(void); +void +TestRecogn(void); + +void +TestRecognExhaustiveKNKP(void); + // // probe.c // @@ -3683,6 +3734,16 @@ RecognLookup(SEARCHER_THREAD_CONTEXT *ctx, SCORE *piScore, FLAG fProbeEGTB); +// +// Unregistered/experimental recognizers, exposed only so testrecogn.c +// can exhaustively validate a candidate before it's ever re-registered +// in InitializeInteriorNodeRecognizers. Not reachable from the normal +// RecognLookup dispatch path. +// +ULONG +_RecognizeKNKP(SEARCHER_THREAD_CONTEXT *ctx, + SCORE *piScore); + SCORE GetRoughEvalScore(IN SEARCHER_THREAD_CONTEXT *ctx, IN SCORE iAlpha, |
