A sketch-error law for gradient kernels

We want N×N similarity matrices of per-token gradients of language models — each selected token position is a datapoint, its gradient one row, and the kernel entry Gij = gidiag(q)gj a inner product in parameter space. Rows are compressed the moment they exist with , so the Jacobian never materializes. This page started as a Pythia-14M pilot ("how wide a hash buys a 1% kernel?") and is now the full study: a 3×2 grid of models (14M / 70M / 410M, embeddings included or frozen out), plus gradient-tail statistics, factored-preconditioner tests, and a measured cost model for the Pythia-1.4B production run.

Sketch error obeys relF ≈ c/√(D·S) at every scale tested, and the constant is a property of the kernel you are estimating, not of the model: c ≈ √(1 + reff), where reff = tr(G)²/‖G‖²F is the kernel's stable rank.

TL;DR — the conclusions, then the evidence:

§1The object, and why sketch it

The motivation is Timaeus-style developmental interpretability: their and susceptibility-spectroscopy line computes essentially this kernel over 4.25M Pile token-contexts of Pythia-1.4B by SGLD sampling. To first order, the loss-fluctuation covariance those samplers estimate is a preconditioned gradient Gram matrix — attackable directly with explicit gradients if the rows can be stored. They can't (4.25M × 1.4B fp32 ≈ 24 PB), so each row is compressed as it is produced:

models
EleutherAI/pythia-{14m, 70m, 410m}, each run with embeddings included and with embed_in/embed_out frozen out ("no-embed"). Peff = hashed params only: 14.1M/1.2M, 70.4M/18.9M, 405.3M/302.0M
data
NeelNanda/pile-10k, packed 512-token sequences
exact subset
N = 256 token losses (120/128 at 410M — a 200 GB memmap guard); exact grads on disk, kernel in fp64 on GPU
sketch ladder
one pass at S = 32,768, D = 4, folded offline to S = 512…16,384; fp32 accumulate, fp16 store
preconditioner
second moment, 256 per-token samples, ε = 1e-8, fp16 runtime
hardware
RTX PRO 4000 Blackwell 24 GB (14M pilot, tails, factored tests) + A100-PCIe-80GB ×2 (70M/410M ladders), torch 2.13 cu130
code
ArcadiaImpact/gradient-kernel

Two methodological details do most of the work. Nested widths: buckets are hash & (S−1), so a sketch computed once at S = 32,768 folds offline to every smaller power of two — each model's entire width ladder is one gradient pass. Same-pass validation: exact rows and sketched features come from the same gradient tensors, isolating sketch error from gradient nondeterminism entirely.

§2The error law across scale

Log-log plot of relative Frobenius error against total sketch width D*S for six runs: Pythia 14M, 70M and 410M, each with and without embeddings. Five of the six series are parallel straight lines of slope one half; the 14M no-embed series bends steeply downward at the widest sketches.
Fig. A · Relative Frobenius error of the sketched kernel vs total width D·S for all six runs, against each run's exact kernel. Solid = embeddings included, dashed = frozen out. Every series is a √-law; the 14M no-embed line (Peff = 1.2M) dives below it once D·S is within ~10× of Peff — the sketch stops being an embedding into a much smaller space.

The fitted law per run, with c also refit at the theoretical α = 1/2 for comparison. Peff counts only the parameters actually hashed — when embeddings are frozen, they contribute neither gradient mass nor sketch dimension, so the no-embed 410M run is a 302M-dimensional problem, not a 405M one:

runPeffNα (free)c (α=½)reff√(1+reff)incoh. p99rows/s
14M incl14.1M2560.561.433.112.030.8584.9
14M −emb1.2M2561.130.881.651.630.2284.0
70M incl70.4M2560.553.5112.53.670.7581.9
70M −emb18.9M2560.484.7823.34.930.0885.4
410M incl405.3M1200.503.9414.93.990.3819.3
410M −emb302.0M1280.494.8523.34.930.0820.1

At 410M the free-fit exponents bracket ½ to two decimal places. The 14M no-embed α = 1.13 is not noise: with Peff = 1.2M, the widest folded sketch (D·S = 131k) is only 9× smaller than the space it compresses, and the error collapses super-JL (visible as the dashed dive in Fig. A). That regime is a bonus at small scale, an irrelevance at 1.4B.

Width still buys downstream quality the way the 14M pilot measured it — top-8 eigenspaces are within a few degrees by D·S ≈ 8–16k while kNN recall@1 keeps climbing through the widest sketch (0.90–0.97 at D·S = 131k across the grid, N-subset dependent): eigenspace work is cheap, neighbour work is expensive.

Three panels showing max principal angle of top-8 and top-32 eigenspaces decreasing with D*S, kNN recall at 1 and 10 increasing with D*S, and max relative error of top-8 eigenvalues decreasing with D*S, measured on the Pythia-14M pilot.
Fig. B · What the width buys downstream (14M pilot, 256-row subset): of top-r eigenspaces, kNN recall under the correlation kernel, worst top-8 eigenvalue error.

§3The constant is the kernel's stable rank

Scatter of measured sketch constant c against the square root of one plus the kernel stable rank, for six runs. The 70M and 410M points lie on the identity line; both 14M points fall below it.
Fig. C · Measured c (refit at α = ½) against √(1+reff) of each run's exact kernel. The four runs with Peff ≫ D·S sit on the line to within 1–4%; the two 14M runs sit below it because they are leaving the JL regime.

Why this law? CountSketch's inner-product estimator has a second-moment identity: the variance of ẑij is (‖xi‖²‖xj‖² + (xixj)²)/(D·S) up to collision terms. Summing over all pairs and normalizing by ‖G‖²F turns the first term into tr(G)²/‖G‖²F = reff and the second into 1, giving relF² ≈ (1 + reff)/(D·S). A kernel of correlated rows — a big shared gradient component, so tr(G)² ≫ ‖G‖²F·1 — is harder to sketch at fixed relative accuracy, because the Frobenius norm you normalize by is concentrated in fewer effective directions. The practical payoff: reff is measurable from a few hundred exact rows (one afternoon at any scale), and then the width for any target error is (√(1+reff)/ε)².

§4Scaling — and the embedding paradox

Two panels: sketch constant c and kernel stable rank versus included parameter count, for embeddings-included and no-embed series. The no-embed stable rank rises to 23.3 by 19 million parameters and stays flat to 302 million.
Fig. D · c and reff vs included parameters. The no-embed stable rank is flat at 23.3 across a 16× span of Peff; the incl-embed series is still rising, but it is rising toward the no-embed plateau as the embedding share of the model shrinks.

Two readings for 1.4B (no-embed Peff = 1.21B): a power-law fit through the three no-embed points gives reff ∝ P0.48 → reff ≈ 70, c ≈ 8.4; the plateau reading gives c ≈ 4.9. But the power-law fit is dragged entirely by the 1.2M-param point — from 18.9M to 302M (a 16× range) reff moved by less than 0.1%. The gradient kernel's effective dimensionality looks like a property of the task and data, not the parameter count, once the model is big enough. We plan with the plateau and carry the power law as the conservative bound (§8).

The embedding comparison resolves into a clean recommendation. Including embeddings lowers reff (14.9 vs 23.3 at 410M) — embedding gradients are dominated by a component shared across tokens, which concentrates the kernel. That actually makes the incl-embed kernel slightly easier to sketch. But it is the wrong kernel to want: the shared component is exactly the part that carries no per-token information, and the price of keeping it is coordinate pathology. In the preconditioner, never-active embedding rows (61% of the vocab in a 1,024-sample estimate at 70M — §5) receive the ε-floor q = 1/ε, orders of magnitude above every live coordinate, and any rare token that does fire at kernel time becomes a heavy hitter: p99 incoherence 0.85/0.75/0.38 with embeddings vs 0.22/0.08/0.08 without, at 14M/70M/410M. CountSketch's known failure mode is colliding heavy hitters; D = 4 tables absorbed it at every scale we ran, but there is no reason to carry the risk. Production: freeze the embeddings.

§5How many gradients does the preconditioner need?

The preconditioner is a per-coordinate mean of squares, so its sample complexity is set by the per-coordinate kurtosis κ = 𝔼[g⁴]/𝔼[g²]²: the relative SE of v̂ after M samples is √((κ−1)/M). We streamed exact fourth moments for every coordinate of Pythia-70M (M = 1,024 incl-embed; M = 512 no-embed):

groupnever activeκ p50κ p99M for 10% v̂M for 10% (p99)
transformer (incl run)0.0%344283.3k43k
transformer (no-embed run)0.0%272692.6k27k
embed_out0.7%393≥M39kcensored
embed_in60.9%≥M≥Mcensoredcensored

Transformer coordinates are heavy-tailed but tractable: ~3k token gradients buy a 10% preconditioner at the median κ, ~30–40k cover the p99 tail. Embedding statistics are censored — a coordinate that fires once in M samples has measured κ = M, and embed_in's κ distribution is pinned at the ceiling (κ tracks 1/activation-frequency, corr(log κ, log freq) = −0.71). Encouragingly, the kernel itself is robust to v̂ noise at M = 1,024 — the ladder fits above were all run off a 256-sample preconditioner and still land on the law — because kernel entries average over millions of coordinates. The ε-floor pathology of §4, not estimator variance, is the real embedding problem.

§6Can the preconditioner be factored?

A full per-coordinate q costs a [P] buffer — 2.8 GB fp16 at 1.4B, held on every GPU. Two cheap approximations, tested against the full preconditioner on Pythia-70M (64-row exact-kernel A/B):

variantstatekernel ρ (incl)kernel ρ (−emb)kNN@1 (−emb)coords within 2×
per-tensor scalar~100 floats0.330.9066%50%
rank-1 (Adafactor-style)~300 KB0.940.99286%88–90%
full per-coordinate2.8 GB fp16 @1.4B11100%100%

The rank-1 variant stores, per weight matrix, a row vector r and column vector c with v̂ = rc/Σv — exactly Adafactor's moment factorization. It reproduces the kernel's off-diagonal structure at ρ = 0.94 (embeddings in) / 0.992 (out) and puts 88–90% of transformer coordinates within 2× of their true preconditioned scale (log-space R² median 0.92 per tensor). The per-tensor scalar collapses with embeddings present (ρ = 0.33, eigenspaces at 90°) and is mediocre without (ρ = 0.90, kNN@1 66%): within-tensor dynamic range is the whole game. One caveat: the no-embed rank-1 A/B shows a top-8 subspace angle of 85° despite ρ = 0.992 — near-degenerate eigenvalues swap order under small perturbations, so subspace angles overstate the damage there; the correlation and neighbour metrics are the honest summary.

The implementation detail that makes this free: a per-token weight gradient is an outer product δa of VJP vectors, so a rank-1 preconditioner applies as (√u ⊙ δ)(√w ⊙ a) — scale the two vectors before the outer product and the [P] preconditioned gradient never exists, not even transiently. Worst rank-1 fits are the stacked QKV matrices (relF 0.84 — three differently-scaled blocks sharing rows) and MLP up-projections (0.42–0.67); factoring QKV per-block is the obvious refinement and would likely close most of the remaining gap.

§7Inside the embedding tables

Four panels: embed_in row variance versus row activation frequency showing strong correlation and 61 percent never-active rows; per-dimension column profiles by token-frequency tercile for embed_in and embed_out showing near-identical shapes; and ANOVA R-squared bars showing row effects dominate while column-only effects explain almost nothing.
Fig. E · Gradient second-moment structure of the embedding/unembedding tables (Pythia-70M, M = 1,024). Left-top: embed_in row variance vs activation frequency (61% of rows never fire). Right-top & left-bottom: per-dim column profiles split by token-frequency tercile — the d_model shape transfers from frequent to rare tokens (corr 0.94–1.0). Right-bottom: log-ANOVA R² of the candidate factorizations.

If one wanted to precondition the embedding tables cheaply anyway, could a single scalar or a d_model vector do it? No: a scalar explains 0% of the log-variance and a column (d_model) vector alone explains 0.1% (embed_in) / 2.5% (embed_out). The structure is token-dominated — row effects carry R² = 0.87/0.97, and embed_out is essentially exactly rank-1 (row+column R² = 0.998). The measurable part is encouraging: the column profile estimated from frequent tokens transfers to rare ones (corr 0.94–0.97 embed_in, 1.000 embed_out), and row scale tracks token frequency (corr 0.59), so unobserved rows could plausibly be filled in as (frequency-predicted row scale) × (shared column profile). That's a research option, not a production recommendation — freezing the embeddings remains the clean answer, and §4's kernel evidence says you lose nothing you wanted.

§8Throughput, and what 1.4B costs

Grouped bar chart of token-gradient rows per second for serial, batched-retain and batched-recompute backends across chunk sizes 1 to 16 on the 14M pilot; serial bars around 80-89 rows/s are solid, batched bars are hatched fallback timings around 35-66 rows/s, with one OOM cell.
Fig. F · Per-token VJP throughput (14M pilot). On torch 2.13, is_grads_batched hits legacy-vmap fallbacks on seven core backward ops, so every batched configuration fails the spec's strict-vectorization rule and loses to plain serial VJPs. Production backend: serial, chunk 4–16 — at every scale in the grid.

The surprising throughput fact: serial per-token VJPs run at ~83–85 rows/s on an A100 whether the model has 1.2M or 70M included parameters — the backward is latency-bound, not FLOP-bound, across that whole range. The FLOP wall arrives between 70M and 400M: both 410M runs land at 19–20 rows/s. Notably 302M and 405M differ by only 4%, so even at 400M the scaling is shallower than 1/P; extrapolating 1/P from the 405M point (6.5 rows/s at 1.4B) is therefore a conservative floor assumption.

Sketching overhead is no longer negligible at the wall. The fused Triton hash sustains 35–61 GB/s at K = 405M on A100 (vs 2.5–9 GB/s for the PyTorch reference) — but the VJP now produces gradients at 19.3 rows/s × 1.62 GB/row ≈ 31 GB/s, so hashing synchronously adds ~50–90% depending on width (it was 11.6% at 14M, where the VJP only produced 4.8 GB/s). Because rows/s falls as 1/P while bytes/row grows as P, this ratio is scale-invariant past the wall: budget 1.5–1.9× the VJP time unless the hash is overlapped onto a side stream (it is memory-bound while the VJP is matmul-bound, so overlap is realistic engineering, not wishful thinking).

The width decision, using §3's law with the §4 readings (no-embed, Peff = 1.21B), and fp16 feature storage for 4.25M rows:

target relFc readingD·S neededconcrete (D=4)achievedfeatures on disk
2%plateau c≈4.961kS = 16,3841.9%0.56 TB
1%plateau c≈4.9243kS = 65,5360.96%2.2 TB
1%power-law c≈8.4714kS = 262,1440.82%8.9 TB

Nested folding removes the risk from this choice: sketch once at the largest width you can afford to store, check c on a small exact subset, and fold down if the plateau reading holds. The compute bill, at the conservative 6.5 rows/s per A100:

hardwareVJP floorw/ sync hashwall-clock (8 GPUs)≈ cost
A100-80GB (measured)182 GPU-h275–345 GPU-h23–43 h$250–480
H100 (estimated ~2.25×)~81 GPU-h~120–155 GPU-h~10–19 h$200–370

The H100 row scales the A100 measurement by a nominal 2–2.5× FLOPs ratio and is an estimate, not a measurement. Everything is data parallel with zero gradient synchronization, so nodes multiply trivially. The preconditioner pass is a rounding error: ~3k rows at 6.5 rows/s ≈ 8 minutes (even the 27k-row tail-grade estimate is ~70 minutes). Against the ~4,800 H200-hours reported for the SGLD-sampled susceptibility version of this object, the sketch route is roughly 20–40× cheaper even at the synchronous-hash ceiling — and, unlike our earlier 14M-only extrapolation (which priced 1.4B at ~1,330 GPU-h by assuming cost ∝ P from 14M), this number is anchored on measured 400M-scale throughput and a measured flat region below 70M.

§9Methods deltas, caveats, next

Code · github.com/ArcadiaImpact/gradient-kernel (spec, plans, 150+ CPU / 8 GPU tests; grid analysis scripts/analyze_ladder_grid.py).
Run artifacts · arcadia-impact/gradient-kernel-pythia14m-pilot-20260713 (14M pilot; grid/tails/factored uploads follow the same org pattern; private).
Figures · scripts/{analyze_ladder_grid, make_embed_structure_fig, make_vibe_figs}.py · pods zemn58cbsa (RTX PRO 4000), l25l320cz + fd5tu5rd (A100).