Parameters per block

With model dim , query heads, KV heads, head dim (usually ), FFN hidden :

Classic case (for MHA, ): , , so LayerNorm/RMSNorm and biases are . Embeddings are not negligible for small models: an 8B model with K and untied embeddings carries B params, 13% of the total.

FLOPs per token

Every parameter participates in one multiply-accumulate = 2 FLOPs: Backward is 2× forward (grad w.r.t. input + grad w.r.t. weights). Activation checkpointing pushes this to .

Attention vs FFN

The term covers the four projections and the FFN, all . The score/value matmuls are and carry no parameters: Set it equal to the weight FLOPs : So for attention only dominates FLOPs past ~49K tokens; for , ~98K. Below that, prefill is a GEMM problem, not an attention problem.

Caveat: this is about FLOPs in prefill. At decode attention dominates time far earlier, because reading the KV cache is memory-bound while the weights are amortized over the batch.

MFU and MBU

Use for training. Prefill MFU of 0.35–0.5 is healthy; decode MFU of 1–5% is normal and not a bug: decode is bandwidth-limited, so measure MBU instead: Good decode systems hit MBU 0.6–0.8. If both MFU and MBU are low, you are latency-bound: kernel launches, collectives, or Python overhead.

Rule of thumb

, forward /token, training /token, attention matters past . Report MFU for prefill and MBU for decode, quoting MFU on a decode benchmark signals you don’t know which roof you’re under.