feat(ci-health): CI-fn training-health telemetry (eval/ci_health/*)#929
Open
ocg-goodfire wants to merge 2 commits into
Open
feat(ci-health): CI-fn training-health telemetry (eval/ci_health/*)#929ocg-goodfire wants to merge 2 commits into
ocg-goodfire wants to merge 2 commits into
Conversation
The CI fn is itself a large trained transformer, but the only visibility into its training health was per-leaf grad norms. Adds the standard big-model instrumentation as scalars on the fast eval cadence, config-gated by a new `CIFnHealth` eval metric: - weights: per (block, matrix) Frobenius norm, spectral norm (batched power iteration over the chunk axis, never full SVD) and stable rank - act: instrumented forward (`ChunkwiseTransformerCIFn.telemetry`) — post-RoPE q/k RMS, attention max/RMS logit + softmax entropy on a <=64-strided query subsample, in_proj / MLP-hidden / residual RMS - logits: mean/std + fractions in the lower-squash zero-gradient (logit > 1) and leak (logit < 0) regions - components: per-site mean-CI participation fraction + dead fraction, site-aggregated (mode-collapse scalars) CIBlock.instrumented deliberately duplicates __call__'s forward math rather than sharing a flagged path: the train step must not carry (or DCE-trust away) the explicit score einsum inside the checkpointed scan. Training numerics untouched; telemetry logits pinned bit-identical to __call__ in tests. JAX-only keys, no torch analog — no SPEC invariant touched (S28-adjacent eval addition). eval/ci_health/* is dropped from the console line (generalized the grad-norms filter); full set rides to wandb + jsonl. Enabled in the pile + llama8b production yamls. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The unrolled 32-iteration python loop over ~50 sharded leaves produced a flat graph whose per-op collectives each wanted registered comm buffers (~50k VMM allocations) — OOM'd a B200 in jit_ci_fn_weight_health at dp=8 (job 167430). Pin each leaf's fp32 copy replicated once (frobenius still reduces on the sharded master), then run the iteration as a collective-free fori_loop with reused buffers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
What
The CI fn is itself a large trained transformer (~10-31B params at 8B scale), but the only in-loop visibility into its training health was per-leaf grad norms. This adds the usual big-model instrumentation as ~220 scalars under
eval/ci_health/*on the fast eval cadence, config-gated by a newCIFnHealthentry ineval.metrics(bridge taskci-function-visibility).Metric families (
param_decomp/ci_health.py, new)weights/{frob,sigma_max,stable_rank}/<block>/<matrix>— per (block, matrix ∈ wq/wk/wv/wo/w1/w2, + in_proj, out_heads): whole-leaf Frobenius norm (same convention as grad norms → update/weight ratios overlay), spectral norm via batched power iteration over the chunk axis (never full SVD — minutes-slow at 32 chunks × 4096²), stable rank‖W‖²_F/σ²_max("weight ranks"). Off the fp32 masters, once per eval pass.act/block{i}/*— from a new eval-only instrumented forward (ChunkwiseTransformerCIFn.telemetry): post-RoPE q/k RMS ("QK norm scales"), attention max/RMS logit + softmax entropy on a ≤64-strided query subsample (logit growth / entropy collapse — the telemetry path materializes the score slab flash never does, hence the subsample), in_proj / MLP-hidden / post-block residual RMS. Chunk-reduced: max for logit-max, mean + worst-chunk_minfor entropy, mean otherwise.logits/*— CI-logit distribution: mean/std + fractions in the lower-squashing zero-gradient (logit > 1) and leak (logit < 0) regions (gradient-starvation signal).components/*— mode-collapse scalars off the per-site mean-CI-per-component vector: participation fraction(Σm)²/(C·Σm²)(mean + min over sites) and dead-component fraction (mean + max).Design notes
CIBlock.instrumenteddeliberately duplicates__call__'s forward math (~15 lines) instead of a flagged shared path: the train step must not carry — or DCE-trust away — the explicit score einsum inside the checkpointed scan. Telemetry logits are pinned bit-identical to__call__in tests; training numerics untouched, no SPEC invariant involved (S28-adjacent, JAX-only keys with no torch analog).fori_loopover a replicated-once fp32 copy per leaf: the first cut (unrolled ×32 over ~50 sharded leaves) demanded ~50k VMM comm-buffer allocations and OOM'd a B200 at dp=8 (job 167430) — the second commit is that fix.eval/ci_health/*is dropped from the console line (generalized the grad-norms verbosity filter); the full set still rides to wandb + jsonl._evalconversion refuses the metric for MLP CI fns.Enabled in
pile_pgd1,pile_ppgd_bsc,llama8b_full32L_HSDP_b32_dp32,llama8b_full32L_HSDP_b128_dp32,llama8b_full32L_seq512_b128_dp128.Validation
param_decomp/tests/test_ci_health.py: telemetry↔__call__logit equality (bitwise), power-iter σ vs full SVD (rtol 1e-2 — fresh-init spectra are near-degenerate, power iter under-estimates ~1%), scalar ranges. Green at default and 4 sim devices.make test: 460 passed, 7 skipped, 11 xfailed.make typeclean.p-c1a10e57): 223eval/ci_health/*keys logged per eval pass, all finite, values textbook at init (attn entropy ≈ log T, stable ranks in the random-matrix ballpark, logit saturation fractions plausible).🤖 Generated with Claude Code