Repository navigation
A100 re-measure: DelaunayNN Sibson launch latency, Phase A (PyAutoArray#533) - #227
Merged
Merged
Conversation
… (PyAutoArray#533) Same-node, same-session A/B on euclid-ral-gpu-2 for PyAutoArray issue #532 Phase A: control at the merge base d7c96762, feature at 9e9a7d50 (chunk 256) and at the shipped e5d31d74 (the new SIBSON_QUERY_CHUNK = 4096 default), plus a 512/1024/2048/4096 chunk sweep with sampled VRAM and the whole-likelihood runtime cell. Jobs 342321-342325, 342329, 342330; the shared /mnt/ral/jnightin/PyAuto install was not touched (private PyAutoArray checkouts prepended to PYTHONPATH). Headline: params->H prefix 143.90 -> 28.21 ms unbatched (5.10x) and 24.32 -> 16.44 ms per call at vmap 16 (1.48x); whole likelihood single-JIT 201.32 -> 76.32 ms (2.64x), vmap-16 per call 58.02 -> 52.62 ms (1.10x). The 29144.581944 pin held exactly on every leg and every chunk. Breakdown cell: adds the --split-setup split-Sibson stage (a prefix stopping after InterpolatorDelaunayNN._mappings_sizes_weights_split, returning all three split arrays so XLA cannot eliminate the walk) so the params->H interval splits into "Split-point Sibson" and "H, ConstantSplit assembly", plus a sibson provenance block in the result JSON (effective caps, mesh query_chunk and the raw PYAUTO_SIBSON_QUERY_CHUNK override). Both delaunay_nn docstrings now state the 4096 default and the env override. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B5HT8dp7sWc9qDhZp6moGr
This was referenced Sep 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A100 re-measure of the DelaunayNN Sibson launch-latency cuts — PyAutoArray issue #532, Phase A, shipped in PyAutoArray #533. This PR carries the profiling-side artifacts: the new
--split-setupsplit-Sibson stage and Sibson provenance in the breakdown cell, the five submit scripts, and the ten job units' results plus the written note.What was measured. All ten job units ran on the same node (
euclid-ral-gpu-2) inside one 28-minute window, so this is a same-session A/B, not a comparison against a recorded baseline:d7c967629e9a7d50(Phase A at the old chunk 256, for the same-chunk A/B) and the shippede5d31d74at the newSIBSON_QUERY_CHUNK = 4096defaultPYAUTO_SIBSON_QUERY_CHUNK, with peak VRAM from a 2 snvidia-smisamplerlikelihood_runtime/imaging/delaunay_nn) on control, feature@256 and shippedJobs
342321–342325,342329,342330. Cell: HST / 3.5" mask / Hilbert-1500 image mesh / MGE-60 lens light / Isothermal + ExternalShear /ConstantSplit, fp64, dense inversion, A100 80GB PCIe. Breakdown flags--split-setup --vmap-batch 16.The shared
/mnt/ral/jnightin/PyAutoinstall was deliberately untouched — the subhalo-validation and Euclid DR1 CPU runs (342299,342311,342314) were live on it throughout. Every leg instead prepends a private PyAutoArray checkout to thePYTHONPATHactivate.shexports, and each job printsautoarray.__file__plus the checkout'sgit rev-parse HEADinto its SLURM log. Recordedxla_flagsare identical on all ten units (--xla_disable_hlo_passes=constant_folding --xla_gpu_autotune_level=0).Headline — control vs the shipped feature
ms per likelihood call;
vmap/16isjax.jit(jax.vmap(fn))at batch 16, reported as batch time / 16.Four-way setup split and the prefixes:
The ±2 ms "Mapping matrix" sign flips are the documented by-difference artifact. The shipped leg's interpolator-prefix
vmapnumber (8.944 ms) is that run's first prefix and carries warm-up; its strict superset in the same run reads 6.434 ms and the sweep's own 4096 row 6.398 ms — read the Sibson share atvmap16 as ≈ 6.4 ms per call.Whole-likelihood runtime cell
vmapbatch 16, per callThe unbatched saving (−125.0 ms) exceeds the params→H prefix drop (−115.7 ms) by the fusion slack expected when the whole pipeline is one program; the batched saving is small for the same reason as #531 — at batch 16 the dense linear algebra dominates.
Pins
EXPECTED_LOG_EVIDENCE_HST = 29144.581944passed unchanged on every leg — both breakdown A/B legs, all four sweep chunks, the shipped re-measure, andpinned_drift: []on all four runtime rows. The chunk is bit-neutral by construction and the sweep proves it end-to-end: five differentlax.mapblock sizes, one log evidence.The witness — half met
vmap16): NOT met. 24.32 → 16.44 ms.The new split-Sibson stage says why, and it is not the Sibson loops. At
vmap16 and the shipped chunk the 16.44 ms decomposes as:The assembly row reads 9.9–10.2 ms at every chunk and on the control — it is untouched by Phase A and cannot be touched by any change to the Sibson chunking. After Phase A roughly 60 % of the per-call params→H prefix is the 33-wide split-stencil regularization assembly, not the Sibson loops. That is why the ≤ 11 ms batched witness could not be met: 10 ms of it was never Sibson's to give. Unbatched the split is the other way round (14.44 ms interpolator prefix vs 13.97 ms assembly out of 28.21 ms) because the 33-wide block build amortises under
vmapwhile the Sibson loops do not.The chunk sweep and the 4096 default
PYAUTO_SIBSON_QUERY_CHUNKswept on the feature checkout; peak VRAM is a 2 s sampler floor on the true peak.9e9a7d50, 342322)e5d31d74, 342329)The 256 row is the same-chunk A/B: it isolates the unroll + single concatenated pass from the chunk change (143.903 → 88.287 ms unbatched, 1.63×). Everything below it is the chunk doing the rest.
Ruling: 4096 ships. The pre-registered rule (plan A.3) was "the largest of 512/1024/2048/4096 whose peak VRAM at
vmap16 stays under ~50 % of the 80 GB and which is fastest per call; if 4096 wins on both, ship 2048 unless the margin is > 15 %". 4096 is fastest on both readings, but the VRAM clause turned out uninformative and was therefore not used to break the tie: the ~41.5 GiB plateau (50.7 % of 81,920 MiB) is identical at every chunk and on the control leg, and the GPU read 0 MiB with no other process at the start of every job — so the plateau is this cell'svmap-16 dense inversion block, not the cavity intermediates. A 16× change of chunk moves it by 8 MiB. The guard arithmetic says why there is room:(C, 3, 2)fp64 intermediates at ~25 kB per query per lane over 4096 queries × 16 lanes is ~1.6 GB, ~2 % of an 80 GB card. With the VRAM leg vacuous the decision rests on speed alone — 4096 is 14.0 % faster per call atvmap16 than 2048 (16.451 vs 19.127) and 9.4 % faster unbatched, a margin the "ship 2048 unless > 15 %" clause would have caught had the VRAM clause been live.PYAUTO_SIBSON_QUERY_CHUNKis kept as the documented escape hatch for a smaller GPU or a much larger cell.Phase B — the numbers, not the decision
Left to the human; recorded here so the call is made on measured figures.
fori_loop→lax.while_loopearly exit) targets the Sibson share only. Its headroom atvmap16 is ~6.4 ms per call; observed cavity occupancy is 11 of the 32 fixed trips, and the plan's own estimate was ~20 % of the remaining Sibson cost — ≈ 1.3 ms per call atvmap16, ≈ 3 ms unbatched.vmap16 — 1.6× the entire Sibson share and 143× Delaunay's equivalent H row. It is a 33-wide split-stencil block-diagonal build (reg_split_from) and nothing in Phase A or B touches it.vmap16 is 52.6 ms per call, so Phase B's ~1.3 ms is ~2.5 % of a production evaluation and the assembly's 10.0 ms is ~19 %.So the bigger per-call lever is a ConstantSplit-assembly rework, not the cavity early exit — by roughly 8× on the batched number production pays. Phase B remains the cheaper, lower-risk change (one loop,
stop_gradientboundary already scoped, no numerical reordering) and is the only one of the two with a written plan; the assembly rework has no prompt yet. Phase C (loop-free k-ring cavity) is now the smallest of the three levers on the batched number and should be re-costed against these figures before it is planned.Scripts Changed
scripts/imaging/likelihood_breakdown/delaunay_nn.py— adds the--split-setupsplit-Sibson stage: a prefix stopping right afterInterpolatorDelaunayNN._mappings_sizes_weights_splitthat returns all three split arrays alongside the step-6 outputs (a strict superset of prefix 6, a strict subset of prefix 11 — return fewer and XLA dead-code-eliminates the walk it exists to measure), yielding the "Split-point Sibson" and "H, ConstantSplit assembly" rows by the same prefix-difference arithmetic. Addssibson_provenance()and asibsonblock in the result JSON (effectiveSIBSON_QUERY_CHUNK/ caps as imported, the mesh's ownquery_chunk, and the rawPYAUTO_SIBSON_QUERY_CHUNKoverride) plussplit_sibson_prefix_snext tointerpolator_prefix_sandregularization_matrix_prefix_s. The step list,steps,setup_splitand every other pre-existing JSON field are unchanged, so older result JSONs stay comparable row-for-row. Docstring records the new 4096 chunk default.scripts/imaging/likelihood_runtime/delaunay_nn.py— docstring only: the recorded Sibson pins now readSIBSON_QUERY_CHUNK = 4096(raised from 256 by PyAutoArray#533) withPYAUTO_SIBSON_QUERY_CHUNKnamed as the import-time override.Submit scripts (new):
hpc/batch_gpu/submit_breakdown_imaging_delaunay_nn_a100_hst_fp64_{launch_latency_control,launch_latency,chunk_sweep}andhpc/batch_gpu/submit_runtime_imaging_delaunay_nn_a100_hst_fp64_{control,launch_latency}. The #531 filesubmit_breakdown_imaging_delaunay_nn_a100_hst_fp64_controlis untouched by this PR.Results Added
results/notes/delaunay_nn_launch_latency.md— the full written record (provenance table, revision table, every table above, the Phase B discussion)results/breakdown/imaging/delaunay_nn_hpc_a100_fp64_launch_latency_control.{json,png}results/breakdown/imaging/delaunay_nn_hpc_a100_fp64_launch_latency.{json,png}(shippede5d31d74, chunk 4096)results/breakdown/imaging/delaunay_nn_hpc_a100_fp64_launch_latency_chunk256.{json,png}(9e9a7d50, the same-chunk A/B)results/breakdown/imaging/delaunay_nn_hpc_a100_fp64_chunk{512,1024,2048,4096}.{json,png}results/runtime/imaging/delaunay_nn/delaunay_nn_hpc_a100_fp64_launch_latency{_control,,_chunk256}.jsonThe 2026-09-07
..._walk_early_exitrows indelaunay_walk_early_exit.mdare left untouched; the control leg here supersedes them for any comparison against this branch (its merge base movedbcd15cd9→d7c96762, and this checkout adds the split-point Sibson cut, so the row sets are not interchangeable).Upstream PR
9e9a7d50+e5d31d74, default chunk 4096)Library-first gate. These results were taken with the feature library on a private checkout, so they are valid regardless of merge order; the breakdown cell's new stage runs against either library (the split-Sibson prefix is defined by the interpolator API, not by the Phase A change). Merge after PyAutoArray#533 like any pending-release workspace PR.
Test Plan
ruff check .— all checks passedruff format --check .— 206 files already formattedscripts/misc/wall/check_submits.py --check— 55 submits with a wall-basis contract, 0 failing, 105 scannedscripts/misc/tooling/build_readme.py --check— 67 versioned artifacts scanned, all READMEs unchangeddelaunay_nnresult JSONs loadhpc/sync.conf(gitignored) not staged; #531's..._fp64_controlsubmit not in the diffGenerated by the PyAutoLabs agent workflow.
🤖 Generated with Claude Code
https://claude.ai/code/session_01B5HT8dp7sWc9qDhZp6moGr