Pick the formula that defines head_dim from hidden_size and num_heads.
head_dim = hidden_size / num_heads, integer divide. hidden_size must be divisible by num_heads or the per-head reshape errors out.
Imagine a 12-pack of soda you want to split evenly into smaller packs. If you want 4 packs, each gets 3 cans. If you want 6 packs, each gets 2. The arithmetic is just: 12 / number of packs = cans per pack. Multi-head attention does the same with a flat hidden vector: split the hidden_size into num_heads chunks, each chunk has head_dim entries, and the math is head_dim = hidden_size / num_heads. If your split does not divide evenly, the soda example breaks the same way the model does: leftover cans, errored reshape.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
The relationship head_dim = hidden_size / num_heads is the cleanest one-line summary of how multi-head attention splits its computation. The formula is enforced by the tensor reshape inside the attention block, has been the standard since the 2017 Transformer paper, and ripples into every design decision around hidden dimensionality, kernel selection, and model scaling.
Most modern LLMs fix head_dim at 128 (kernel-friendly) and pick hidden_size and num_heads to satisfy the constraint. Some recent architectures (MLA in DeepSeek V4) decouple the relationship via explicit projections, but those are exceptions and the standard formula is what an interview expects. This deep dive walks the reshape that enforces the constraint, the parameter-count motivation from the original Transformer, common configurations across model sizes, how GQA relates to the formula, and the MLA exception that decouples per-head dimensionality from the simple identity.
The reshape that enforces the formula
Multi-head attention's core operation is a tensor reshape from a flat hidden vector into a per-head 2D block. Understanding this reshape is the whole reason the formula has to hold.
The data flow
- Input tensor shape:
(batch, seq_len, hidden_size). - Q, K, V projections: each is a linear layer of shape
(hidden_size, hidden_size). Output:(batch, seq_len, hidden_size). - View into heads:
(batch, seq_len, num_heads, head_dim). - Transpose for attention:
(batch, num_heads, seq_len, head_dim). - Attention matmul:
(batch, num_heads, seq_len, seq_len)for the scores, then(batch, num_heads, seq_len, head_dim)for the output. - Transpose back:
(batch, seq_len, num_heads, head_dim). - View to flat:
(batch, seq_len, hidden_size). - Output projection: linear
(hidden_size, hidden_size).
Where the constraint lives
The critical step is view(batch, seq_len, num_heads, head_dim). PyTorch's view is a zero-copy reshape that requires the product of the target dimensions to equal the product of the source dimensions. For this view:
num_heads * head_dim == hidden_size
If the product mismatches, view raises a RuntimeError. There is no rounding, no padding, no implicit truncation. The constraint is hard.
What this means practically
When designing a transformer, you must pick hidden_size and num_heads such that the division is exact. head_dim is not a free choice; it is determined by the other two. The standard interview answer captures exactly this:
head_dim = hidden_size / num_heads, with hidden_size % num_heads == 0
Situations where this technique stops working.
2–4 min · Everything important, quickly.
Real products, models, and research that use this idea.
- GPT-2 small: hidden_size = 768, num_heads = 12, head_dim = 64.
- BERT base: hidden_size = 768, num_heads = 12, head_dim = 64 (same as GPT-2 small).
What an interviewer would ask next. Try answering before peeking at the approach.
QWhat happens at runtime if you try to build a model with hidden_size = 800 and num_heads = 12?
800 / 12 = 66.67, which is not an integer. PyTorch's MultiheadAttention raises an assertion error at construction time: AssertionError: embed_dim must be divisible by num_heads. Hugging Face implementations raise a similar error. The model cannot be built with this configuration; you must either change hidden_size to a multiple of 12 (792 or 816) or change num_heads to a divisor of 800 (8, 10, 16, etc.).
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Treating head_dim as a free hyperparameter independent of hidden_size and num_heads. It is locked: head_dim = hidden_size / num_heads, with hidden_size % num_heads == 0 required.
60 second bullets to scan on the way to the call.
The exact formula head_dim = hidden_size / num_heads
The divisibility requirement hidden_size % num_heads == 0
Primary sources. Browse if you want the original framing.
Same topic, related formats. Practice these next.