Skip to the lesson
FixTheRobot Explore Robotics / LLM / LM10 Modern LLM Architecture and Inference / LM10-T3

LLM · Theory · LM10

LM10-T3 — Multi-Query and Grouped-Query Attention

Keep all the query heads, share the key and value heads. The cache shrinks by the group size, while the attention layer loses only a little of its parameters and, in published comparisons, little of its quality.

  • Lesson 3 of 6
  • Module 10: Modern LLM Architecture and Inference
  • Theory
  • Difficulty: Advanced
  • About 9 minutes to read
  • Prerequisite: LM10-T2

When a model generates text it must store the keys and values of every previous token, in every layer. For a long context and many users that cache is larger than the model. Multi-head attention gives every query head its own key head and value head, which is more flexibility than quality needs. Multi-query and grouped-query attention share them. This lesson shows exactly what is shared, counts the savings with real configuration numbers, implements the idea in a few lines of PyTorch, and explains how to choose the number of groups. Lab LM10-L2 lets you count the options; Lab LM10-L1 shows the effect on a serving budget.

Learning objectives

After this lesson, you should be able to:

  • Describe MHA, GQA and MQA by the number of key-value heads.
  • Compute attention parameters and KV-cache bytes per token for each.
  • Implement grouped-query attention by repeating key-value heads and test it.
  • Choose a number of key-value groups for a memory budget and explain the quality risk.

The idea: queries need diversity, keys and values less so

In multi-head attention (Module 3), a layer with H heads projects every token to H queries, H keys and H values. Head j compares its query with the keys of head j and mixes the values of head j. The heads learn different patterns: one follows syntax, one looks at the previous token, one retrieves a name from far back.

During training everything is computed at once, and the number of key and value heads is a question of parameters and arithmetic, nothing dramatic. During generation it is different. At every step the model needs the keys and values of all earlier tokens, and recomputing them would be wasteful, so they are stored: the KV cache (Lesson LM10-T5). The cache has H key heads and H value heads per layer per token and has to be read from memory at every step. It is the largest memory object in long-context serving.

The observation behind MQA and GQA is that the queries carry most of the head diversity. Several query heads can ask different questions of the same set of keys and values. So share the keys and values:

Multi-head, grouped-query and multi-query attentionThree columns, each showing eight query heads in a row and the key-value heads they use below them. Multi-head: eight key-value heads, one per query head. Grouped-query: two key-value heads, each shared by a group of four query heads. Multi-query: a single key-value head shared by all eight query heads. The number of cached key-value heads is 8, 2 and 1 respectively.Multi-head (MHA)q1q2q3q4q5q6q7q8kv1kv2kv3kv4kv5kv6kv7kv88 cached key-value headscache × 1Grouped-query (GQA)q1q2q3q4q5q6q7q8kv1kv22 cached key-value headscache × 1/4Multi-query (MQA)q1q2q3q4q5q6q7q8kv11 cached key-value headcache × 1/8
Eight query heads in all three layouts. Multi-head attention has one key-value head per query head; grouped-query attention shares each key-value head among a group; multi-query attention shares one key-value head among all queries.
  • MHA: Hkv = H. Maximal flexibility, maximal cache.
  • MQA (Shazeer, 2019): Hkv = 1. Minimal cache, noticeably lower quality and sometimes unstable training.
  • GQA (Ainslie et al., 2023): 1 < Hkv < H, typically 8. Intermediate cache, quality close to MHA in the published experiments.

What does not change

The number of query heads, the width of the layer’s output, the causal mask and the softmax are all unchanged. A group of H/Hkv query heads simply reads the same stored keys and values. The attention computation is the same; only the keys and values are repeated, conceptually, across the group.

Why it also speeds up decoding

A decode step reads the weights and the whole cache from memory (Lesson LM10-T5). A smaller cache means less to read for long contexts, and it allows larger batches. The speed-up is therefore largest for long contexts and many concurrent requests, which is where serving is expensive.

A trade-off, not a free lunch

The mathematics: shapes, parameters and cache

Let d be the model width, H the number of query heads, Hkv the number of key-value heads (dividing H), dh the head width, and g = H/Hkv the group size. For input X of shape (B, T, d):

projections: the query has H heads, keys and values have Hkv
Q=X⋅WQ→(B, H, T, dh)Q=X\cdot W_{Q}\to (B,\,H,\,T,\,d_{h})
K=X⋅WK→(B, Hkv, T, dh)K=X\cdot W_{K}\to (B,\,H_{\text{kv}},\,T,\,d_{h})
V=X⋅WV→(B, Hkv, T, dh)V=X\cdot W_{V}\to (B,\,H_{\text{kv}},\,T,\,d_{h})

Query head j (0-based) uses key-value head ⌊j/g⌋. Equivalently, repeat each key-value head g times along the head dimension (repeat_interleave) to get shape (B, H, T, dh) and apply ordinary attention:

attention of query head j
Oj=softmax⁡(Qj⋅K⌊jg⌋⊤dh+mask)⋅V⌊jg⌋O_{j}=\operatorname{softmax} (\frac{Q_{j}\cdot K_{\frac{\lfloor j}{g\rfloor }}^{\top}}{\sqrt{d_{h}}}+\text{mask})\cdot V_{\frac{\lfloor j}{g\rfloor }}
WQ
d × (H·dh); unchanged by sharing.
WK, WV
each d × (Hkv·dh): this is where the parameters are saved.
WO
(H·dh) × d; unchanged.
g
group size; query heads j = ig … ig + g − 1 share key-value head i.

Parameters

no biases
Pattn=d⋅H⋅dh+2⋅d⋅Hkv⋅dh+H⋅dh⋅dP_{\text{attn}}=d\cdot H\cdot d_{h}+2\cdot d\cdot H_{\text{kv}}\cdot d_{h}+H\cdot d_{h}\cdot d

Cache per token

keys and values (factor 2), L layers, b bytes per number
cache per token=2⋅L⋅Hkv⋅dh⋅b\text{cache per token}=2\cdot L\cdot H_{\text{kv}}\cdot d_{h}\cdot b

The 7B configuration (d = 4,096, H = 32, dh = 128, L = 32, 16-bit):

Parameters and cache for the 7B configuration
LayoutHkvAttention parameters / layervs MHACache per tokenvs MHA
MHA3267,108,864100%524,288 B100%
GQA-8841,943,04062.5%131,072 B25%
GQA-4437,748,73656.3%65,536 B12.5%
MQA134,603,00851.6%16,384 B3.1%

The cache falls in proportion to Hkv, but the attention parameters fall only to half at the extreme, because the query and output projections (2d2 of the original 4d2) are untouched. Sharing is therefore worth it for the cache, not for the parameter count. With a 32-layer model, 8,192-token contexts and 16 concurrent requests, the cache is 68.7 GB with MHA and 17.2 GB with GQA-8 (Lab LM10-L1).

Converting a multi-head checkpoint

A model trained with MHA can be converted: for each group of g heads, average their key projection matrices into one and likewise the value projections (mean pooling), then continue training for a small fraction of the original compute so that the model adapts. The GQA paper reports that this “uptraining” recovers most of the quality at a few percent of the original training cost, and that mean pooling beats keeping only one head of each group. Converting without any further training generally damages quality.

A worked example: implement and test GQA

The first block counts parameters and cache for the layouts of the table. The second implements grouped-query attention for the small shapes of Notebook LM10-L3, and tests three facts: with two key-value heads and eight query heads the output equals ordinary multi-head attention on the repeated heads; query heads of one group do not depend on another group’s keys; and the cache holds a quarter of the numbers.

import torch

def counts(d, nq, nkv, hd, layers, bytes_=2):
    params = d * nq * hd + 2 * d * nkv * hd + nq * hd * d
    cache_token = 2 * layers * nkv * hd * bytes_
    return params, cache_token

for name, nkv in (('MHA', 32), ('GQA-8', 8), ('GQA-4', 4), ('MQA', 1)):
    p, c = counts(4096, 32, nkv, 128, 32)
    print(name, p, c, round(c / 524288, 4))
# MHA 67108864 524288 1.0
# GQA-8 41943040 131072 0.25
# GQA-4 37748736 65536 0.125
# MQA 34603008 16384 0.0312

def attend(q, k, v):
    """q: (B, Hq, T, hd); k, v: (B, Hkv, T, hd). Each key-value head serves Hq // Hkv query heads."""
    rep = q.shape[1] // k.shape[1]
    k, v = k.repeat_interleave(rep, dim=1), v.repeat_interleave(rep, dim=1)
    scores = q @ k.transpose(2, 3) / q.shape[-1] ** 0.5
    mask = torch.triu(torch.ones(q.shape[2], k.shape[2], dtype=torch.bool), diagonal=1)
    return torch.softmax(scores.masked_fill(mask, float('-inf')), dim=-1) @ v

torch.manual_seed(0)
B, T, hd = 1, 5, 4
q = torch.randn(B, 8, T, hd)
k, v = torch.randn(B, 2, T, hd), torch.randn(B, 2, T, hd)
out = attend(q, k, v)
print(out.shape)                                                # torch.Size([1, 8, 5, 4])

k8, v8 = k.repeat_interleave(4, dim=1), v.repeat_interleave(4, dim=1)
print(torch.allclose(out, attend(q, k8, v8)))                   # True: same as MHA with copied heads

k2 = k.clone(); k2[:, 1] = torch.randn(B, T, hd)                # change the keys of group 1 only
out2 = attend(q, k2, v)
print(torch.allclose(out[:, :4], out2[:, :4]), torch.allclose(out[:, 4:], out2[:, 4:]))   # True False
print(k.numel() + v.numel(), k8.numel() + v8.numel())           # 80 320: a quarter of the stored numbers

Query heads 0 to 3 are untouched when the keys of group 1 change, and heads 4 to 7 change: each query head depends on exactly one key-value head. The cache stores 80 numbers instead of 320 for this tiny example.

Choosing the number of groups

  1. Fix the target,Memory left after the weights, the context length and the number of concurrent requests you must serve.
  2. Compute the cache,2 · L · Hkv · dh · b · n · B for candidate values of Hkv (powers of two dividing H).
  3. Check the quality,Compare your evaluation scores for the candidates, trained or converted, with the confidence intervals of Module 9.
  4. Check the speed,Measure decode throughput at the real batch size and context length; the gain grows with both.

Engineering implications and limitations

Eight is a common choice. Many open models use around 8 key-value heads regardless of size. It cuts the cache by 4 to 8× relative to MHA for 32 to 64 query heads, and the group size is large enough for most of the saving and small enough to keep quality.

Keep the cache before repeating. Store the Hkv heads, not the repeated H. Repeating is a view or a cheap copy that you do at attention time; storing the repeated tensors throws away the whole saving.

Tensor parallelism interacts. When the layer is split across devices by heads, the number of key-value heads must be compatible with the number of devices; with too few heads some devices hold copies of the same one.

Test equality with MHA. Setting Hkv = H must reproduce ordinary multi-head attention exactly. Keep that test in your suite.

Read the configuration. A checkpoint states Hkv in its configuration (often called the number of key-value heads). Loading it into code that assumes MHA gives shape errors at best and wrong text at worst.

Account for both budgets. The parameter saving (about 12% for GQA-8 in the example model) pays for part of a bigger model at the same size; the cache saving pays for concurrency and context length. Report both.

Common misconceptions

“GQA reduces the number of attention heads.”

It keeps all query heads; only the key and value heads are shared.

“The cache saving equals the parameter saving.”

The cache falls with Hkv; the parameters fall only in the key and value projections.

“MQA is just a smaller model.”

It has the same width and number of query heads; only the stored keys and values are shared.

“Sharing never hurts quality.”

Multi-query attention measurably does; grouped-query attention is a compromise whose loss must be measured for your model.

“You can switch a trained MHA model to GQA at inference time.”

Without averaging the heads and brief further training, quality drops.

Engineering takeaways

  1. MHA, GQA and MQA differ only in the number of key-value heads Hkv; the number of query heads stays H.
  2. Attention parameters: d·H·dh + 2·d·Hkv·dh + H·dh·d. Cache per token: 2·L·Hkv·dh·b.
  3. In the 7B example GQA-8 keeps 62.5% of the attention parameters and 25% of the cache; MQA keeps 51.6% and 3.1%.
  4. Implement by repeating each key-value head g times at attention time; store only Hkv heads in the cache.
  5. Convert MHA checkpoints by mean-pooling the heads of each group and uptraining briefly; choose Hkv by memory budget and measured quality.

References and further reading

The parameter and cache numbers in the table were computed by the code in this lesson for a generic 7-billion-parameter configuration. The cited papers give the quality and speed measurements; this lesson does not reproduce them.

  • Shazeer, N. (2019). Fast transformer decoding: One write-head is all you need. arXiv:1911.02150.
  • Ainslie, J. et al. (2023). GQA: Training generalized multi-query transformer models from multi-head checkpoints. arXiv:2305.13245.
  • Touvron, H. et al. (2023). Llama 2: Open foundation and fine-tuned chat models. arXiv:2307.09288.
  • Ainslie et al. (2023), GQA (research paper)
  • Shazeer (2019), Multi-Query Attention (research paper)

Knowledge check

Three conceptual questions. Write an answer, then reveal the explanation. Your answers stay in your browser.

Question 1

A layer has 40 query heads, 8 key-value heads and head width 128. How many query heads share each key-value head, and what is the cache per token per layer in 16 bits?

Explanation

Group size 40 / 8 = 5. Cache per token per layer: 2 × 8 × 128 × 2 bytes = 4,096 bytes.

Question 2

Why does multi-query attention save a large share of the cache but only about half of the attention parameters?

Explanation

The cache holds only keys and values, which shrink by the factor Hkv / H. The parameters also include the query and output projections, which are unchanged and make up half of the multi-head attention parameters (2d² of 4d²).

Question 3

A colleague stores the repeated key and value tensors (shape B, H, T, dh) in the cache of a GQA model. What goes wrong?

Explanation

The numerical results are right, but the cache is H / Hkv times larger than necessary, so the memory saving that motivates GQA is lost and long contexts or many concurrent requests may no longer fit.

What’s next

Next: SwiGLU, RMSNorm and mixture of experts, the changes to the feed-forward half of the block.

Practice this lesson

Compare Attention Variants

Count parameters, cache size and compute for multi-head, multi-query and grouped-query attention.

Next lesson

LM10-T4 — SwiGLU, RMSNorm and Mixture of Experts

Explain gated feed-forward layers, RMS normalization and sparse expert routing.

Nothing below is required to finish this lesson.