diff options
| author | Scott Gasch <[email protected]> | 2026-09-25 08:44:25 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-09-25 08:44:25 -0700 |
| commit | 9b28080f8b3dca4588cb2aaaf748451f45e3c626 (patch) | |
| tree | 54e0aff5d6ee1520c590c7c04a5ae2f8299e7497 /src/CLAUDE.md | |
| parent | 66740dc89c7351c120c25788d0079055034f4942 (diff) | |
Two ideas:
1. Nullmove R=3 + depth/6 along with some ShouldWeDoNullmoveSearch
tweaking and calibrating.
2. Probe EGTB everywhere in the search as long as the table/position
is resident in memory.
Diffstat (limited to 'src/CLAUDE.md')
| -rw-r--r-- | src/CLAUDE.md | 76 |
1 files changed, 69 insertions, 7 deletions
diff --git a/src/CLAUDE.md b/src/CLAUDE.md index b545edd..0bfc028 100644 --- a/src/CLAUDE.md +++ b/src/CLAUDE.md @@ -162,13 +162,75 @@ an xboard-protocol REPL on stdin/stdout. Key commands used during development: configure Syzygy tablebase lookup. **Default EGTB path is hardcoded** in `main.c:297` to `/zscratch/egtb`, used -whenever `--egtbpath` isn't passed. That directory currently has full 5-man -WDL+DTZ Syzygy coverage but is **missing the WDL half of its 6-man set** (only -`.rtbz`/DTZ files exist for 6-man combos) -- `init_tb()` in -`fathom/tbprobe.c:752` requires the WDL file to exist before registering a -combination at all, so every 6-man entry is silently skipped and the engine -reports "up to 5 men" even though 6-man `.rtbz` files are sitting right there. -Not a config issue; the fix is downloading the missing 6-man `.rtbw` files. +whenever `--egtbpath` isn't passed. That directory now has **full 5-man and +6-man WDL+DTZ Syzygy coverage** (the earlier gap -- 6-man `.rtbz`/DTZ files +present but the `.rtbw`/WDL half missing, so `init_tb()`'s +`fathom/tbprobe.c:752` WDL-file-required check silently skipped every 6-man +combination and the engine reported "up to 5 men" -- has been closed by +downloading the missing 6-man `.rtbw` files). `TB_LARGEST` should now read 6 +at startup. + +### Predicting whether a deep probe will be cheap (memory) vs. expensive (disk) + +Historically the engine only probed the EGTB shallow/near-root (`search.c`'s +`RecognLookup` call gated its 3rd arg, `fProbeEGTB`, on +`ctx->uPly <= (g_uIterateDepth / 2)`, and QSearch's call hardcoded `FALSE` +-- never probed at all in qsearch) specifically to avoid stalling the tree +search on a disk read near the leaves, where nodes are cheap and plentiful +and a single blocking read would be ruinously expensive relatively speaking. + +That blanket avoidance left value on the table: once a few pieces have +traded off near a leaf, a position is often *already* covered by a +tablebase whose file was mapped into memory by an earlier, shallower probe +this same search -- Fathom (`fathom/tbprobe.c`) lazily `mmap()`s + parses +each material signature's `.rtbw`/`.rtbz` file exactly once per process, +on first probe, behind a double-checked-locking `atomic_bool +be->ready[type]` (`probe_table`, `tbprobe.c:1778`). Once `ready[WDL]` is +true for a given material signature, subsequent probes of that signature +are just memory/page-cache lookups, not disk reads -- but the old +depth-based gate couldn't tell the difference between "warm" and "cold" +material and refused all deep probes uniformly. + +Fixed by adding `tb_wdl_is_resident()` (`fathom/tbprobe.c`, declared in +`fathom/tbprobe.h`) -- a non-blocking check that recomputes the same +material-signature key Fathom's own `calc_key()` uses (pure per-side +piece-type popcounts, no square/turn/ep info needed, so no board +conversion required) and reads `be->ready[WDL]` for that signature. No +lock, no file I/O, just a handful of popcounts + one atomic load; safe to +call from every leaf-ish node. Wrapped as `EgtbProbeLikelyResident(ctx)` +in `probe.c` (mirrors `ProbeEGTB`'s castling/fifty-move/cardinality +gating, so it never claims a probe is "likely resident" that `ProbeEGTB` +itself would refuse outright). `search.c`'s two `RecognLookup` call sites +now pass `(ctx->uPly <= (g_uIterateDepth / 2)) || EgtbProbeLikelyResident(ctx)` +(main search) and `EgtbProbeLikelyResident(ctx)` (QSearch, which +previously never probed at all) instead of the old ply-only / hardcoded +`FALSE` gates. + +**Caveat**: `ready[WDL] == true` only proves the file's header/index +metadata was parsed, not that every compressed data page this specific +position's lookup will touch is already resident in the OS page cache. +For the small 3-5 man files that distinction is essentially moot in +practice (the whole file tends to end up page-cached after the first +touch); for large 6-man files it's a weaker guarantee -- a `ready` +6-man table can still have cold pages. Not yet measured empirically +whether this matters in practice; if deep-probe latency spikes show up +in profiling, this is the first place to look. + +**Not yet done, a natural follow-up**: root-time warm-up -- proactively +touching (probing) WDL tables for material signatures reachable within a +few plies of likely trades from the root position, before the main +search starts, so `ready[WDL]` is already true for most of what the deep +search will actually encounter rather than depending on an earlier +shallow-ply probe in the *same* search to have warmed it first. + +**Also worth knowing**: `ProbeEGTB` wraps the actual `tb_probe_wdl` call +in a single process-wide spinlock (`g_uEgtbLock`, `probe.c`). Increasing +probe frequency deep in the tree (now possible via the above) increases +contention on that spinlock under `MP=1` multithreaded search even when +every probe individually is memory-cheap -- not yet measured whether this +becomes a bottleneck in practice; if throughput regresses under multiple +threads after this change, check spinlock contention before assuming a +disk-latency cause. ## Testing: the ECM tactical suite |
