summaryrefslogtreecommitdiff
path: root/src/testnnue.c
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-10-14 13:15:31 -0700
committerScott Gasch <[email protected]>2026-10-14 13:15:31 -0700
commitba0eac31639a3eb076ad17e8cd40f57990a53c00 (patch)
treee50998859828f03b5cd01436a720cb46190af511 /src/testnnue.c
parentd91da8c2f4d16ce6beeb11f503f4041b4d8d8d54 (diff)
Unify HelpSearch() onto SearchOneMove (UNIFY_SEARCH.md step 4)
HelpSearch() now calls the same per-move kernel Search() uses (searchsup.c's SearchOneMove, extracted in step 2), instead of its own hand-rolled inline copy. This is the actual unification: helper threads gain the real CanWeReduceOrPruneMove() gate (9 base checks + 2 move-identity exemptions) and ShouldLatePrune()'s LMP, neither of which HelpSearch had before -- its old inline LMR-only gate was missing the SEE-negative-capture carve-out, the mate-magnitude-alpha check, fThreat, and both killer/countermove exemptions. It also now gets real attack-table snapshots (bbMinorAttacksSnapshot/ bbRookAttacksSnapshot) and fThreat from g_SplitInfo (step 3's plumbing), instead of the zeroed snapshots and missing-fThreat degraded inputs the old inline LMR lookup used. Per-call parameter mapping, not obvious from SearchOneMove's search.c call site alone: - x is chosen so (x - 1) reproduces mv's absolute index in ctx->sMoveStack (uBegin[ctx->uPly] + uMoveNum, computed pre-MakeMove while ctx->uPly is still the split ply) -- the same relationship search.c's own x maintains for its callers inside the kernel. - uLegalMoves is passed PRE-increment (g_SplitInfo[u].uAlreadyDone + uMoveNum, not + 1): SearchOneMove itself increments it once right after MakeMove succeeds, so passing the already-"+1" value would double-count relative to what the old inline code's uSplitLegalMoves computed. - fFullWindow is always FALSE (a helper thread's first pulled move is never this node's actual first move -- uAlreadyDone >= 1 always, since a split only launches after the originating thread already searched at least one move with the full window). - fIsGeneratedMoveStage is always TRUE, fIsLeftoverMove is always TRUE -- both already true of every move HelpSearch handles, same as the removed inline code's own assumptions. - MOVE_ORDERING_EVIDENCE_COLLECTION/TEST_NULL instrumentation gets FALSE/0/throwaway-output -- confirmed with the user these diagnostics are single-threaded-only by design, not a gap to fill. Two real, DEBUG-only invariant breaks found and fixed getting this to pass under real multithreading (both confirmed via a DEBUG=1 --cpus 4 stress run across all three curated suites, not just the fast smoke test): 1. SearchOneMove's own post-UnmakeMove sanity ASSERT compares against ctx->sPlyInfo[ctx->uPly].sPosition (pi->sPosition), which Search() populates once at node entry -- but a helper thread never calls Search()/CommonSearchInit for the split-point ply itself (see eNodeType's own SPLIT_INFO comment), so that slot was stale leftover data from whatever unrelated node the thread last helped with. Fixed by having HelpSearch() populate it itself, once before the move loop, matching Search()'s own convention. 2. StartParallelSearch's post-split DEBUG assert ("fail-low implies every candidate was searched", split.c ~line 801) no longer holds universally: a helper thread can now legitimately stop pulling moves from a failing-low split via MOVE_KERNEL_ABORTED when WE_SHOULD_STOP_SEARCHING's MP definition fires for a reason unrelated to this split's own outcome (ThreadUnderTerminatingSplit -- an ANCESTOR split up this thread's call stack terminated). The old inline code never checked WE_SHOULD_STOP_SEARCHING explicitly, so it never bailed early for this reason either; this is a correctness improvement (stop grinding through a doomed split's remaining moves once told to), not a regression, so the assert was loosened to tolerate it rather than reverting the early-exit. Verified: precommit_check.sh passes. Bit-identical node counts at sd10/--cpus 1 unaffected (confirmed again), as expected -- the single-threaded path never calls HelpSearch(). DEBUG=1 --cpus 4 sd10 run across all three curated suites (191 positions): clean exit, zero assertion failures, after both fixes above. Not yet done: the solve-count/fail-high-rate comparison at --cpus 4 against head_reference/baseline_cpus4_pre_unification.md -- a single run was taken (71/191 vs the baseline's 81/191) but --cpus 4 is confirmed genuinely nondeterministic (real races across splits, not noise-free), so a one-shot diff isn't a meaningful comparison either direction. A real comparison needs match_play.py-style repeated trials, not done here. head_reference/ itself not yet rebuilt as the new baseline pending that. Co-Authored-By: Claude Sonnet 5 <[email protected]>
Diffstat (limited to 'src/testnnue.c')
0 files changed, 0 insertions, 0 deletions