Skip to content

fix(fmm): honor explicit traversal config in the production large-N clamp#48

Merged
TobiBu merged 1 commit into
mainfrom
fix/honor-explicit-traversal-config-large-n
Jul 23, 2026
Merged

fix(fmm): honor explicit traversal config in the production large-N clamp#48
TobiBu merged 1 commit into
mainfrom
fix/honor-explicit-traversal-config-large-n

Conversation

@TobiBu

@TobiBu TobiBu commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Problem

On the production large-N GPU radix path, _clamp_gpu_traversal_config_for_memory
(jaccpot/runtime/fmm_overrides.py) reduced even a caller-supplied (explicit)
DualTreeTraversalConfig down to the fixed streamed minimum-memory ceiling
(_GPU_STREAMED_MINIMUM_MEMORY_EXPLICIT_PAIR_QUEUE_XL = 524288). That ceiling is a
constant, far below the traversal frontier a concentrated multi-million-particle disk
actually needs (~2N pairs). Because fail_fast is force-enabled in strict-fused mode,
the undersized queue does not degrade gracefully — it raises:

RuntimeError: Traversal capacity overflow with fail_fast enabled.
Pair queue capacity exceeded; increase max_pair_queue and rebuild.
Current capacities: max_pair_queue=524288, ...

Net effect: a deliberate, memory-fitting user override is silently clamped and the run
crashes during prepare at N ≳ 2M on ≥40 GB GPUs — even though the run fits in memory.
Concretely, a 4M-particle exponential-disk simulation on an A100-40GB (which steady-states
at ~36 GB) could not be launched at all through the standard --fmm-max-pair-queue path.

Root cause

The method has four memory-safety blocks. Three of them already skip when
_explicit_traversal_config is set — only the production-large-N ceiling block clamped
regardless. That asymmetry is the bug: the memory-safety auto-clamps are meant for the
auto-sized/default path, not to override caps a caller explicitly chose for their hardware.

Fix

Gate the production-large-N ceiling clamp on not self._explicit_traversal_config, making
it consistent with the other three blocks:

  • Explicit traversal config → honored (trust the caller's hardware-sized caps).
  • Auto-sized (non-explicit) config → still bounded to the streamed ceiling (unchanged).

One-line condition change + an updated comment explaining the rationale.

Test

tests/unit/test_traversal_clamp_honors_explicit.py (CPU-only; drives the clamp directly
with backend_name="gpu", no real GPU needed):

  • test_explicit_traversal_config_is_not_clamped_on_production_large_n — explicit 16M
    pair-queue passes through unclamped. Fails before this change (clamped to 524288),
    passes after.
  • test_autosized_traversal_config_still_bounded_on_production_large_n — non-explicit
    config stays ≤ ceiling (guards the safety net).

Verified against a real 4M-particle A100-40GB run: with the fix the explicit caps reach the
traversal and the run completes at 36.3 GB (identical to the last known-good large-N
benchmark); without it, the prepare phase overflows.

Alternative considered

An env override for the ceiling (mirroring _minimum_memory_streamed_gpu_traversal_seed,
which already reads JACCPOT_LARGE_N_GPU_MIN_MEMORY_*) would also work, but honoring the
explicit config is more principled and matches the existing behavior of the sibling blocks.

🤖 Generated with Claude Code

…rge-N)

The production large-N GPU memory-safety clamp
(_clamp_gpu_traversal_config_for_memory) reduced even a caller-supplied
(explicit) DualTreeTraversalConfig down to the fixed streamed minimum-memory
ceiling (max_pair_queue 262144/524288). Under static fixed sizing that ceiling
is far below the traversal frontier a concentrated multi-million-particle disk
needs, so with fail_fast on it turned a deliberate, memory-fitting override into
a hard "Pair queue capacity exceeded" overflow at N >= ~2M on >=40 GB GPUs
(e.g. a 4M-particle A100 disk that otherwise fits at ~36 GB).

Static fixed sizing means "use the sizes I gave you", so it now passes an
explicit traversal config through unclamped (new honor_explicit_traversal=True
at that call site). Auto-sized *preset* seeds are still bounded (Block 1 + the
ceiling), and the adaptive path (static sizing off) still clamps explicit caps
for adaptive memory management -- so the existing
test_large_gpu_minimum_memory_streamed_path_caps_oversized_explicit_traversal
contract is unchanged.

Adds tests pinning both: static sizing honors an oversized explicit config;
adaptive sizing still caps it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@TobiBu
TobiBu force-pushed the fix/honor-explicit-traversal-config-large-n branch from c119ad9 to 279d567 Compare July 23, 2026 07:51
@TobiBu
TobiBu merged commit d42a845 into main Jul 23, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants