Grouped-Query Attention
Instead of every head keeping its own keys and values or all heads sharing one pair, grouped-query attention splits heads into a handful of groups where each group shares a KV pair — most of the cache saving, almost none of the quality loss.
Why Does This Exist?
Multi-query attention solved the KV cache problem aggressively: collapse all heads to one shared KV pair and you get an H-fold reduction in cache memory. The problem was quality. Models trained with a single shared KV pair showed measurable degradation on tasks that relied on heads attending from different angles — translation, long-document QA, coding tasks where context structure matters.
Ainslie et al. at Google (2023) asked whether you actually need to go all the way to one group. They ran a systematic ablation: train the same model with G groups where G ranged from 1 (MQA) to H (full MHA), and measure the quality-cache trade-off at each point. The answer was that G=8 or so recovered nearly all of MHA's quality while cutting the KV cache by 4× compared to MHA. G=1 (MQA) saved more cache but paid meaningfully more in quality. The sweet spot existed, and it wasn't at either extreme.
That finding shipped as Llama 2 70B (8 KV groups out of 64 query heads) and Mistral 7B (8 groups out of 32), among others. Grouped-query attention is now the default in virtually every open-weight model that runs in production.
Think of It Like This
Table groups at a conference
Picture 32 researchers at a conference, seated at 8 tables. Every researcher at a table shares the same reference binder — the keys and values their group uses. Each researcher still writes their own question (query), and each table's binder is slightly different from the others. The researchers at table 1 have one binder; table 2 has its own; but within a table, the binder is shared.
This is grouped-query attention. Eight different binders instead of 32 separate ones (MHA) or one shared binder for the whole room (MQA). The reduction in binders translates directly to a reduction in the KV cache.
How It Actually Works
Projections and grouping
In GQA, query heads are divided into G groups. Each group gets one K projection and one V projection, each of shape . The query projection stays full: H separate projections, each .
Concretely: if you have H=32 query heads and G=8 groups, each group serves H/G=4 query heads. The KV cache is G times smaller than MHA — 8× smaller here, versus 32× smaller with MQA.
The attention computation per group
For a group serving heads :
Every head in the group uses the same and , but because differs per head, the attention pattern and output differ per head. The model learns to spread its representational load across the G groups — a constraint it adapts to during training, which is why GQA benefits most when trained from scratch rather than retrofitted.
Uptraining from MHA
It's possible to adapt a trained MHA checkpoint to GQA by mean-pooling the H KV heads into G groups and then continuing training briefly. The Ainslie et al. paper showed this "uptraining" on roughly 5% of the original training tokens recovered most of the quality gap, making it a practical option for adapting existing models.
Show Me the Code
Measuring the KV cache for MHA, GQA, and MQA at model-serving scale.
import numpy as np
seq, d_model, H, d_head = 4096, 4096, 32, 128 # LLaMA-style
def kv_cache_gb(n_groups, seq_len, d_head, n_layers=32, dtype_bytes=2): """KV cache in GB for both K and V across all layers.""" return 2 * n_groups * seq_len * d_head * n_layers * dtype_bytes / 1e9
mha = kv_cache_gb(H, seq, d_head)gqa_8 = kv_cache_gb(8, seq, d_head)gqa_4 = kv_cache_gb(4, seq, d_head)mqa = kv_cache_gb(1, seq, d_head)
print(f"MHA (32 groups): {mha:.2f} GB")print(f"GQA (8 groups): {gqa_8:.2f} GB ({mha/gqa_8:.1f}× smaller than MHA)")print(f"GQA (4 groups): {gqa_4:.2f} GB ({mha/gqa_4:.1f}× smaller than MHA)")print(f"MQA (1 group): {mqa:.2f} GB ({mha/mqa:.1f}× smaller than MHA)")# MHA (32 groups): 2.15 GB# GQA (8 groups): 0.54 GB (4.0× smaller than MHA)# GQA (4 groups): 0.27 GB (8.0× smaller than MHA)# MQA (1 group): 0.07 GB (32.0× smaller than MHA)At 4,096 tokens GQA with 8 groups still needs 0.54 GB per request for the KV cache alone — relevant at high concurrency, where the number of active caches multiplies by the number of simultaneous users.
Watch Out For
Treating group count as a quality knob you can tune at inference time
The number of KV groups is baked in during training. A model trained with 8 groups cannot be re-run with 4 or 16 groups without retraining. Group count is an architectural choice, not a serving parameter. Set it before you train.
Expecting uptraining to fully close the gap
Uptraining an MHA checkpoint to GQA works but leaves a small quality gap that only full training from scratch closes. For a production model where quality matters, train with GQA from the start. Reserve uptraining for research or resource-constrained adaptation.
The Quick Version
- GQA divides H query heads into G groups; each group shares one KV pair instead of having one per head (MHA) or sharing one across all heads (MQA).
- KV cache is G times smaller than MHA, so G=8 out of H=32 gives a 4× reduction.
- Quality is near-MHA quality — the quality drop relative to MHA is measurably smaller than MQA's.
- Group count is fixed at training time, not a serving dial.
- Most modern open-weight models (Llama 2 70B, Mistral, Gemma 2) use GQA as the default.
What to Read Next
- Multi-Query Attention is the predecessor GQA improved on — one KV group total, maximum cache saving, more quality loss.
- Multi-Head Latent Attention takes a different approach to the same problem — compress K and V into a low-rank latent rather than grouping heads.
- Multi-Head Attention is the baseline GQA approximates, with one KV pair per head.
- Attention Complexity covers the quadratic cost that makes KV cache size a real constraint.
- KV Cache explains the caching mechanism that GQA directly reduces.