summaryrefslogtreecommitdiff
path: root/src/CLAUDE.md
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-09-25 08:44:25 -0700
committerScott Gasch <[email protected]>2026-09-25 08:44:25 -0700
commit9b28080f8b3dca4588cb2aaaf748451f45e3c626 (patch)
tree54e0aff5d6ee1520c590c7c04a5ae2f8299e7497 /src/CLAUDE.md
parent66740dc89c7351c120c25788d0079055034f4942 (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.md76
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