perf(compile): kill the init-compile share of the cold start (ci-fn 167s→4.4s, sources 55s→<2s) + compile-time attribution#954
Closed
danbraunai-goodfire wants to merge 13 commits into
Closed
Conversation
…per-arm cache isolation, JAX_LOG_COMPILES) Cherry-pick of ffc7b67 from bridge/task-reduce-jax-compilation-time. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E34cK5BaVr6ZFAwRidNp6n
…omp_vu init_decomp_vu_placed compiled a single graph with 2 x n_sites sharded outputs (448 at 32L); the SPMD partitioning/layout pass over that many distinct outputs was a 3m31s compile at 32L/dp128 (210.5s -> 16.3s measured on GPU at the full 224-site shape set). It now compiles two cheap stages: the RNG runs vmap-STACKED per V/U shape (init_decomp_vu_stacked: 2 x n_shapes sharded outputs), then a trivial slice jit (unstack_decomp_vu, stacked input donated) fans out to the per-site ZeRO-1 layout. BIT-identical to the previous jitted per-site init (vmap over the same per-site keys); test_sharding now pins exact equality against the jitted per-site reference (the unjitted eager reference differs from ANY jitted path by ~1 ULP of XLA fusion — pre-existing, previously hidden by allclose). Extracted from the bridge task branch (PR #941). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E34cK5BaVr6ZFAwRidNp6n
Submitting from inside a SLURM allocation (agent sessions, dev pods) leaked the caller's SLURM_CPUS_PER_TASK into the new job, whose srun then died with 'cpus-per-task set by two different environment variables' (the same leak the btdr launch wrapper works around by hand). sbatch now submits with a clean env so the job's SLURM state comes only from its own allocation.
Attributes jit_step compile time to graph sections: chunk count 1/2/4/8, PPGD warmup scan, PPGD term, faith term, plus a per-XLA-pass timing arm. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E34cK5BaVr6ZFAwRidNp6n
…8 exceed HBM) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E34cK5BaVr6ZFAwRidNp6n
…MPILES visibility) dictConfig defaults disable_existing_loggers=True, which killed jax's loggers — JAX_LOG_COMPILES and persistent-cache diagnostics never reached the slurm log. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E34cK5BaVr6ZFAwRidNp6n
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E34cK5BaVr6ZFAwRidNp6n
… across graph structure) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E34cK5BaVr6ZFAwRidNp6n
Round-3 probe (dp32, production shape, isolated caches) split the cold-start compile pie: jit_step 288s, jit_build_ci_fn 167s, jit_init_persistent_sources 55s. The latter two are the init_decomp_vu disease again: - init_chunkwise_transformer_ci_fn unrolled n_chunks python-side chunk inits and stacked them (32 copies of the chunk RNG body in one graph); now eqx.filter_vmap over the same fold_in keys — bit-identical stacks, one-chunk graph. - init_sources_sharded emitted n_sites (224) sharded outputs; now the V/U two-stage recipe: vmap-stacked per C group, then a donated slice jit fans out per site. Bit-identity pinned in test_sharding (uniform draws are pure threefry bit-ops). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E34cK5BaVr6ZFAwRidNp6n
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E34cK5BaVr6ZFAwRidNp6n
…/CLAUDE.md Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E34cK5BaVr6ZFAwRidNp6n
The arm configs are throwaway probe artifacts, regenerable from gen_grid_arms.py; fastinit (A/B of a now-landed fix) and nofaith (faith is mandatory in build_loss_terms on this branch) removed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E34cK5BaVr6ZFAwRidNp6n
…t tooling, not library code The grid generator hardcoded cluster paths (btdr data mount, scratch dirs) and a base config; the repo stays cluster-independent. The findings + method live in CLAUDE.md, the raw logs + launch configs are archived on btdr. compile_probe/ reverts to its feature/jax state. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E34cK5BaVr6ZFAwRidNp6n
Collaborator
Author
|
I'm not sure about this, leaving it on the shelf.
|
Collaborator
Author
This was referenced Jul 6, 2026
Collaborator
Author
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.

Description
Compile-time investigation follow-through (continues #941/#951). A controlled probe grid on and-btdr — one production-shape arm per mutation (full 32L / 224 sites / full C / dp32), each with an isolated XLA cache — attributed the cold-start wall to individual compiles. The headline: the historical "~20–24 min before step 0" was mostly the serial init compiles, not
jit_step, and the graph-structure refactors previously scoped forjit_stepwould buy ~nothing.Fixes (both the
init_decomp_vurecipe from #951, bit-identity pinned by tests):init_chunkwise_transformer_ci_fnunrolled n_chunks python-side chunk inits and stacked them (32 copies of the chunk RNG body in one graph). Noweqx.filter_vmapover the samefold_inkeys.jit_build_ci_fn: 167s → 4.4s measured at the production shape.init_sources_shardedemitted n_sites (224) sharded outputs. Now the two-stage form: vmap-stacked per C group, then a donated slice jit fans out per site.jit_init_persistent_sources: 55s → under the 2s log threshold.param_decomp/log.py:dictConfigwas disabling jax's already-created loggers (disable_existing_loggersdefaults True) —JAX_LOG_COMPILES=1and persistent-cache diagnostics never reached slurm logs. One line.Measured attribution (probe grid, docs added to
param_decomp/CLAUDE.md):jit_stepcompile is flat across every graph-structure knob: recon chunks 1/2/4/8 = 383/262/306/365s (noise band), halved C ≈ 289s, 2-block CI fn ≈ 289s, PPGD warmup on/off ≈ −45s, PPGD removed ≈ −70s. Topology slope mild: dp32 ≈ 290–306s → dp64 ≈ 345s. Pass profile (TF_CPPhlo_pass_pipelinearm): ~83% priority-fusion. The scan-over-recon-chunks follow-up scoped in perf(compile): 13x faster V/U init compile + compile-time findings #941 is not worth doing for compile time.No measurement tooling ships in this PR — the probe configs were one-shot artifacts (cluster-specific paths), so the method is documented in
param_decomp/CLAUDE.mdand the raw logs + launch configs are archived on btdr (compile_probe_grid_2026-07-06_logs.tgz). Every file in the diff is cluster-independent library code.Stacked on #951 (contains its commit
b676138cc; also duplicates the sbatch env-scrub commit from #941). Merge #951 first and this rebases to just the new work.Related Issue
Continues the bridge task
reduce-jax-compilation-time(#941, #951).Motivation and Context
Every new-config launch paid ~7 min of pure init compiles before the step compile even started; sweeps paid it per arm. The init fixes remove that entirely, bit-identically. The attribution data stops us from spending a core-trainer refactor (chunk scan) on a cost that measurement shows it cannot move.
How Has This Been Tested?
array_equal), stacked sources vs per-siteinit_persistent_sources(exact, incl. bf16 storage dtype) — intest_shardingat 1 and 4 sim devices.make test(same 4 pre-existingtest_slow_evalfailures on cleanfeature/jax),tests/equivalencegoldens pass,make check/make typeclean.fastinitarm vsbase4arm — ci-fn 167→4.4s, sources 55s→<2s,jit_stepunchanged (~260–275s vs ~290–306s, within the arm noise band).Does this PR introduce a breaking change?
No. Init values are bit-identical; the log change only re-enables foreign loggers.
🤖 Generated with Claude Code
https://claude.ai/code/session_01E34cK5BaVr6ZFAwRidNp6n