Training Compute Accounting
One number describes a training run: parameters times tokens times six. Knowing where the six comes from is what lets you tell when it stops being true.
Standing
Current standardPart of the default recipe. Present in most frontier models trained today, and the thing a new design departs from rather than argues for.
The unit every scaling result is expressed in. Accurate to a few percent for dense transformers, and wrong in specific ways for MoE and for long context.
judged as of 2026-09 · what the labels mean
Theory
Every scaling result is a statement about , and is almost always computed rather than measured.
parameters, training tokens, and a constant of six. It is worth being able to derive the six, because the derivation says exactly when it fails.
Where the six comes from
Consider one weight in one matmul, and one token.
Forward: 2. The weight is used once, in a multiply-accumulate — one multiply, one add. Two FLOPs.
Backward: 4. Two products are needed, not one. The gradient with respect to the input propagates the error down the network, and the gradient with respect to the weight is what the optimiser consumes. Each is a matmul of the same shape as the forward, so each costs two FLOPs per weight per token.
Six FLOPs per parameter per token, and multiplying by and gives eq. 1.
When it breaks
Long context. The attention term is per sequence against ‘s — so it matters when . At and it is a few percent; at it dominates, and quoting 6ND for a long-context run understates the cost several-fold.
Mixture of experts. must be the active parameter count, not the total. DeepSeek-V3 is 671B parameters and 37B active; using the former overstates its training cost by eighteen times. Every MoE scaling comparison depends on which is meant, and papers are not always explicit.
Recomputation. Full checkpointing repeats the forward pass, making the constant 8. Megatron-style selective recomputation puts it near 6.5.
Embeddings. Kaplan et al. excluded embedding parameters from ; Hoffmann et al. included them. At small scale that is a large fraction of the model and the two conventions disagree materially — which is part of why the two papers’ conclusions differ.
Implementation
def training_flops(
layers: int, d_model: int, vocab: int, seq: int, tokens: int,
d_ff: int | None = None, checkpointing: bool = False,
) -> dict[str, float]:
"""FLOPs for a dense decoder. Returns the 6ND estimate and the correction."""
d_ff = d_ff or 4 * d_model
# Per layer: 4d² of attention projections, 2·d·d_ff of feed-forward.
per_layer = 4 * d_model**2 + 2 * d_model * d_ff
n_non_embed = layers * per_layer
n_total = n_non_embed + vocab * d_model
factor = 8 if checkpointing else 6
simple = factor * n_total * tokens
# Attention's parameter-free matmuls: QKᵀ and AV, forward and backward.
attention = 12 * layers * seq * d_model * tokens
return {"6ND": simple, "with_attention": simple + attention,
"attention_share": attention / (simple + attention)}Why it is worth carrying
The estimate is what makes disparate runs comparable. A 70B model on 15T tokens is FLOPs whatever hardware ran it, and that number can be placed on the same axis as a 7B model on 2T. Every plot in Chinchilla and everything downstream of it depends on the comparison being sound.
It is also the basis of the regulatory thresholds now written into law, which are stated in FLOPs and computed exactly this way — a detail that makes the active-versus-total question for MoE considerably less academic than it looks.