Foundations

Attention Mechanisms

Advanced

MHA, MQA, GQA, MLA, and sliding-window attention - what each variant is, why it exists, and exactly how each shapes the KV-cache memory bill.

Queries, keys, values, and the KV cache

At each transformer layer, every token projects into three vectors: query (Q), key (K), and value (V). Attention computes softmax(QKᵀ/√d) · V - the query vector “asks” which tokens are relevant; the key vectors surface those tokens; the value vectors carry their content. During inference, newly generated tokens must attend to every previously seen token, so the K and V tensors from those prior tokens are saved to GPU memory rather than recomputed - that is the . The size of that cache is what makes attention variant selection a first-class infrastructure decision, not just a model-quality tradeoff. See the KV cache deep-dive for the full picture.

KV-cache bytes per token - the formula, drawn

Every term is one dimension of the block a single token leaves in the cache. Pick a model or change the K/V heads and precision; hover or tap a term to light up its dimension.

num_kv_heads
precision
×
×
×
×
=
131 KBper token

bytes = 2 × num_layers × num_kv_heads × head_dim × bytes_per_element

Khead_dim 1288 kv heads32 layers (12 drawn)+Vhead_dim 1288 kv heads32 layers (12 drawn)
one square per byte · each value = 2 B
× sequence length= 16.8 GB for one request

Multiply by batch size to get total GPU memory consumption. Only num_kv_heads changes between MHA, GQA and MQA - the other terms are fixed by the model's depth, width and serving precision.

Multiply by sequence length to get total cache for one request; by batch size to get total GPU memory consumption. Model Sizing & Parallelism covers the full memory budget.

Multi-Head Attention (MHA)

The original Vaswani et al. formulation. The hidden dimension is split into H parallel heads, each learning independent Q, K, and V projections. This lets different heads specialize in different relational patterns simultaneously - some attend to syntax, others to coreference, others to positional proximity. Critically, every query head has its own K/V head, so num_kv_heads = H. That makes the most expressive variant and the one with the largest KV cache. At 32 heads, BF16, 32 layers, and head_dim = 128, each token costs 32 × 32 × 128 × 2 × 2 = 524 KB - and that cost accumulates linearly with sequence length.

MHA: one K/V head per query head, for every token

Each row is a query head wired to its own K/V head (8 of 32 drawn). Every token appends a K/V pair to every row, on every layer - pick a context length to watch the cache grow.

query head → own K/Vcached →

One orange cell = 512 tokens of K/V for that head · repeated on all 32 layers

Context length

524 KB/token × 8,192 tokens

4.3 GB

0grows linearly with seq_len128K

For one request, at BF16. Multiply by concurrent requests for the GPU-wide bill.

Strengths

  • ▸Maximum representational capacity - the baseline every other variant is compared against
  • ▸Well-studied; most hardware and kernel optimizations target MHA first
  • ▸Flash Attention / Flash Attention 2 make prefill fast by tiling into SRAM

Limitations

  • ▸Largest KV cache of all variants - scales as H × layers × seq_len
  • ▸Memory bandwidth during decode is proportional to num_kv_heads; high H hurts throughput
  • ▸Impractical for very long context without complementary techniques

Multi-Query (MQA) and Grouped-Query (GQA) attention

Both variants reduce num_kv_heads below H, which directly shrinks the KV cache and the memory-bandwidth cost of decoding.

Blue circles are query heads; squares are the Key/Value heads that get cached. Fewer K/V heads = smaller KV cache. MHA, GQA, and MQA sit on one continuum - they differ only in how many query heads share each K/V head.

MHA

8 KV heads
8 query headscached K/V

1× cache (baseline)

GQA (G=2)

2 KV heads
8 query headscached K/V

¼× cache

MQA

1 KV head
8 query headscached K/V

⅛× cache

MHA gives every query head its own K/V head - maximum expressiveness, largest cache. MQA collapses all heads onto one shared K/V - smallest cache, some quality loss. GQA is the middle ground production models settled on: a handful of K/V heads keeps quality near MHA while shrinking the cache 4–8×.

Multi-Query Attention (MQA)

num_kv_heads = 1

All H query heads share a single K/V head. The KV cache shrinks by roughly 1/H - an 8-head model uses 1/8 of the MHA footprint. The tradeoff is expressive capacity: all heads see the same key and value, so the diversity MHA relies on is eliminated. At moderate model sizes this leads to measurable quality regression; larger models tolerate it better. Noam Shazeer proposed MQA in 2019 precisely to accelerate autoregressive decode. Used by Falcon, early PaLM, and early Gemini variants.

Grouped-Query Attention (GQA)

num_kv_heads = G

Query heads are partitioned into G groups; all heads in a group share one K/V head (so each K/V head serves H/G query heads). At G = H you recover MHA; at G = 1 you have MQA. In practice G = H/4 or H/8 (e.g., 8 KV heads for 32 query heads) offers the sweet spot: near-MHA quality with a 4–8× smaller cache. Llama 2 and Llama 3 both use , as do Mistral and Gemma. Ainslie et al. (2023) showed GQA checkpoints can be obtained by mean-pooling MHA checkpoints, making retrofitting practical.

Decode bandwidth intuition: At each decode step the GPU streams K/V tensors from HBM. With GQA at G = 8 instead of H = 32, you stream 4× fewer bytes per step - which translates nearly linearly to 4× higher decode throughput when the bottleneck is HBM bandwidth, not compute.

K/V heads read from HBM per layer, per cached token (32 query heads)

MHA32 heads · 1×
GQA (G=8)8 heads · ¼×
MQA1 head · 1/32×

Multi-head Latent Attention (MLA)

Introduced in DeepSeek-V2 (2024) and carried into DeepSeek-V3, takes a fundamentally different approach: instead of storing H separate K/V heads per token, it compresses the entire K/V representation into a single low-rank latent vector per token per layer. During decoding, the full K/V matrices are reconstructed from that latent on the fly.

Hidden state (full d_model)down-projectlatent cd_c≈512← all that'scachedup-projectW_K, W_V (weights)KVK and V - rebuilt per head, on the flynever cached - reconstructed each step

What actually gets cached per token - to scale

MHA
full K/V, every head
MLA
one latent + RoPE key

~93% smaller per token (DeepSeek-reported, vs an equal-dimension MHA model).

Standard attention caches full K and V for every head (large). MLA caches only the small shared latent c and reconstructs K/V during attention. The up-projection matrices are permanent weights, so they cost memory once - not once per token.

MLA also handles positional encodings through a decoupled mechanism: separate positional K heads are cached in full to avoid the incompatibility between low-rank compression and position-dependent rotations. The full architecture is detailed in the DeepSeek-V2 technical report.

Why DeepSeek's MLA is different - and why it wins

~70 KB / token · 61 layers

Step through the four ideas that make MLA work - each tab pairs a picture with the detail.

GQA / MQA - share headsdrop K/V heads, keep 2 of 8
cached
MLA - compresskeep every head, cache one latent
ccached → rebuilt at attention time:

Solid = stored in the cache per token · dashed = reconstructed, never stored.

For each token, the model projects the hidden state down to a compressed latent vector c (where d_c << d_model). Only c is cached. At attention time, K and V are recovered via up-projection matrices W_K and W_V - these matrices are shared across all heads and all positions, so they live in parameters (permanent weights), not the per-token cache.

GQA and MQA save memory by throwing away K/V heads (sharing them across queries). MLA keeps full per-head expressiveness but caches a single learned low-rank latent (d_c = 512) instead of the heads themselves - reconstructing K and V from it at attention time. It's compression, not head-sharing.

DeepSeek reported the 93.3% figure and MHA-parity quality (measured against a hypothetical equal-dimension MHA model), and third-party analyses partly echo them. Numbers reflect DeepSeek-V2 (60 layers) / V3 (61 layers).

Sliding-window and sparse attention for long context

Even with GQA or MLA, KV-cache memory grows linearly with sequence length. A 128K-token context at BF16 with Llama 3 8B (GQA, 8 KV heads, 32 layers, head_dim 128) still consumes roughly 128 000 × 131 KB ≈ 16.8 GB. Sparse attention variants cap this growth by restricting which tokens each position can attend to.

Each row is a token deciding which earlier tokens it can attend to (a lit cell = allowed). Full causal attention lets every token see all of its history - the lit area, and the KV cache, grow without bound. Sliding-window caps each token to the last 4 positions, so the cache stays a fixed size no matter how long the sequence gets.

Full causal

cache O(seq_len)
row = query position ↓column = key position →

Sliding window (W=4)

cache O(W)
row = query position ↓column = key position →

Sparse attention patterns, side by side

Each grid is an attention mask: row = query position, column = key position, lit = allowed. Tap a pattern for details (12 positions, illustrative window and dropped keys).

row = query ↓key →

Sliding window

Mistral, Mixtral
Sliding-Window Attention (SWA): Each token attends only to the W most recent tokens (the “window”). The KV cache per layer is capped at W entries regardless of sequence length, making memory consumption O(W) rather than O(seq_len). Mistral 7B uses W = 4096 on alternating layers while keeping a few full-context layers for global coherence - the “Mistral pattern.” Mixtral extends this with a sparse stack. The limitation: tasks requiring attention across tokens further than W apart (e.g., recalling details from the beginning of a long document) degrade unless global layers compensate.
attended

Most open long-context models mix the two: gpt-oss alternates 128-token sliding-window layers with full-attention layers, Gemma 3 and 4 run five sliding-window layers per global one, and Llama 4 confines three of every four layers to 8K-token chunks - so only the global layers grow with context.

Playground: see each variant side by side

Switch between the variants to watch two things change at once: which Key/Value heads get cached (left) and which tokens each position is allowed to attend to (right). GQA and sliding-window expose a slider so you can feel the memory-vs-quality tradeoff directly.

Attention playground - one cache, two ways to shrink it

The grid is the KV cache for one layer: each row is a cached K/V head, each column a token. Play to decode tokens and watch it grow; switch variants to see head sharing remove rows, MLA replace them with a latent, and a sliding window stop the columns. Toy model: 8 query heads, head dim 128 (illustrative).

K/V groups G

G = 8 is MHA · G = 1 is MQA

1/12Token t1 decoded · 1 column cached

GQA: t1 decoded, 512 values cached per layer (MHA: 2,048).

KV cache for one layer

query headstokens →t1t2t3t4t5t6t7t8t9t10t11t12
values cached per layer 512MHA 2,048 · 25%

1 tokens × 2 K/V heads × 2 × 128 = 512

cell = K (top) + V (bottom) query head not yet decoded

Who t1 can attend to

key position →query position ↓

Row t1 attends to all 1 keys so far, so every column must stay cached.

GQA - Grouped-Query Attention

Query heads share K/V heads in groups, so the grid loses rows. Fewer groups = smaller cache, slightly less expressive.

KV bytes per token across attention generations

Every attention generation since 2017 has largely been an argument about one number: how many bytes the model must keep for each token it has already seen. A 70B model with full multi-head attention caches about 2.5 MiB per token; grouped-query attention cuts that 8×, DeepSeek's latent attention (MLA) compresses it to about 69 KiB, and DeepSeek V4.1-Flash gets it down to about 890 bytes by compressing tokens, storing values and letting most layers reuse another layer's cache. Switch the metric to see what that means for a whole sequence at 128K or 1M tokens - and how sparse attention changes a different number: how many cached tokens each new token reads.

Context

KV cache bytes per token (whole model, log scale)

1 KiB10 KiB100 KiB1 MiB
  • The MLA cache plus a small indexer key per token (128 dims in FP8) - it stores slightly more than MLA and saves reads, not memory.

Tap a row for what it stores. Each step down the ladder changes what is cached, not just how it is read.

MHA through the hybrid row assume a BF16 cache (FP8 would halve them); the DeepSeek V4 rows use their FP8/FP4 layouts. Illustrative: MHA. Exact arithmetic from the model config: GQA-8, MLA, Kimi K3. Estimates from the config plus an assumed cache layout: DSA (FP8 indexer key), V4-Pro and V4-Flash (576 B per compressed entry, 64 B FP4 indexer key). Model-card figure: V4.1-Flash, 890 B, which the config reproduces (4 KV layers × 356 B at 2:1, 2:1, 2:1 and 1:1). Read counts are averaged over attention layers and leave out the indexer's own scan.

Variant comparison

The table below compares all five variants on the dimensions that matter for infrastructure sizing.

VariantKV heads (vs. MHA)Relative cache sizeQuality impactExample models
MHA

Multi-Head Attention

H (one per query head)1× (baseline)Baseline - no compromiseGPT-2/GPT-3, Llama 1, BERT
MQA

Multi-Query Attention

1 (shared by all heads)≈ 1/HSlight loss at large H; faster decodeFalcon, PaLM, Gemma 2B
GQA

Grouped-Query Attention

G (1 < G < H)G/HNear-MHA; sweet spot at G=H/4 or H/8Llama 2/3, Mistral, Gemma
MLA

Multi-head Latent Attention

Latent vector (low-rank)Small - model-specificNear-MHA quality at a fraction of the cacheDeepSeek-V3, Kimi K2, Mistral Large 3
SWA

Sliding-Window Attention

H, but bounded window WW/seq_len (capped)Degrades on tasks requiring full global attentionMistral 7B, Gemma 3/4, gpt-oss

Relative cache size assumes constant layers, head_dim, and precision. MHA = H heads; GQA relative size = G/H (varies by config). For SWA the bounded window W replaces seq_len - cache does not grow beyond W regardless of context length. Exact figures depend on model architecture. See the KV cache calculator and model sizing for your specific config.

Worked examples: bytes per token

Applying the formula to real and illustrative model configs at BF16 (2 bytes/element) shows how starkly the variants diverge. Bars are scaled to the largest row (524 KB).

ModelVariantLayersKV headsHead dimKV bytes/token
Llama 3 8BGQA32812832 × 8 × 128 × 2 × 2 = 131 KB
Llama 3 70BGQA80812880 × 8 × 128 × 2 × 2 = 328 KB
GPT-style (illustrative MHA, 32 heads)MHA323212832 × 32 × 128 × 2 × 2 = 524 KB
Llama 4 Scout (17B-16E)GQA48812848 × 8 × 128 × 2 × 2 = 197 KB*hatched = dense upper bound
Qwen3-235B-A22BGQA94412894 × 4 × 128 × 2 × 2 = 193 KB
Gemma 3 27BGQA621612862 × 16 × 128 × 2 × 2 = 508 KB*hatched = dense upper bound
DeepSeek-V3 (MLA)MLA61-latent 512+64≈ 61 × 576 × 2 = 70 KB
Kimi K2 (Moonshot, MLA)MLA61-latent 512+64≈ 61 × 576 × 2 = 70 KB
DeepSeek-V2 (MLA)MLA60-latent 512+64≈ 60 × 576 × 2 = 69 KB

DeepSeek MLA figures are approximate - the cached latent is c = 512 per layer plus a decoupled RoPE key (≈ 64 dim), so V2/V3/Kimi K2 cache 576 per layer. *Gemma 3 and Llama 4 Scout are dense upper bounds: Gemma 3 interleaves sliding-window and global layers (5:1) and Llama 4 caps three of every four layers at 8K-token chunks, so their real long-context caches are far smaller than shown. KV bytes per token multiply by sequence length to get total cache for one request.

Try it: interactive comparator

Dial in a model config and context length to see how the per-token and total KV cache diverge across all four variants - and how the gap widens with longer context and more concurrent requests.

How many users fit? Same model, four attention variants

The only thing that changes between rows is how many K/V vectors each token caches per layer. Follow that one factor from a single token, to bytes per token, to how many long requests fit on a GPU node.

Request length32K
Model weights in HBM140 GB ≈ 70B params at BF16140 GB
KV precision
Model shape · 80 layers · 64 query heads · head dim 128 · GQA G = 8

1 · What one token caches in one layer

MHA
…K ×64
…V ×64
2 × 64 × 128 = 16,384 values
GQA
K ×8
V ×8
2 × 8 × 128 = 2,048 values
MQA
K
V
2 × 1 × 128 = 256 values
MLA
c·512
latent + RoPE key, shared by all 64 heads
512 + 64 = 576 values
K head V headcell width = head dim (128 values); long groups collapse to "…×N"

Why they differ: MHA caches a K and a V for every one of the 64 query heads. GQA lets 8 query heads share each K/V pair; MQA lets all 64 share one. MLA caches one learned latent that every head rebuilds its K and V from.

2 · KV bytes per token, all 80 layers (log scale, fixed axis)

1 KB10 KB100 KB1 MB10 MB100 MBMHA2.62 MBGQA328 KB · 8.0× lessMQA41 KB · 64× lessMLA92 KB · 28× less

3 · 32K-token requests that fit on one 8× H100 (DGX/HGX)

640 GB HBM − 140 GB weights = 500.0 GB left for KV

MHA
5 requests85.9 GB each
GQA
46 requests10.7 GB each · 9.2× MHA
MQA
372 requests1.34 GB each · 74× MHA
MLA
165 requests3.02 GB each · 33× MHA

One square per request, each at full length. KV only - activations and fragmentation are ignored, so real numbers are lower.

Per request = bytes per token × request length. Same layers, head dim and precision: the attention variant alone moves this node from 5 to 372 concurrent 32K-token requests.

Decision guide: picking attention for a memory budget

These cards are not architecture choices - if you are serving an existing model, the variant is fixed. They are useful for evaluating new model choices or advising teams building from scratch.

Pick your constraint

Choose the scenario closest to yours; the strip lights the variant(s) that fit it.

MHAH heads
GQAG heads
MQA1 head
MLAlatent c
SWAwindow W
Sparsereads top-k
Hybridstate + few layers

Recommendation

GQA (G = H/8 or H/4)

Cuts KV cache by 8–4× versus MHA with minimal quality cost. The Llama 3 family proves this works at 70B+ scale.

Going deeper: the 2025-26 research frontier

Everything above is enough to size a KV cache for today's models. The newest designs go further: attention that reads only part of the cache, linear-attention layers that swap the cache for a fixed-size state, and small changes to sinks, gating and position encoding that decide how far a model can stretch its context.