Multi-Head Latent Attention
Instead of caching full key and value tensors for every head, compress them into a tiny shared latent vector and reconstruct the per-head K and V on the fly — the cache stores the latent, not the expanded tensors.
Why Does This Exist?
MQA and GQA both trim the KV cache by sharing projection weight across heads. The cache shrinks by 1/H or 1/G. But you're still caching tensors whose size scales with the number of tokens times the head dimension — at long contexts and high concurrency that remains a hard ceiling.
Multi-head latent attention (MLA), introduced with DeepSeek-V2 in 2024, attacks the problem differently. Instead of sharing projections across heads, compress the K and V tensors before storing them using a low-rank down-projection, cache the compressed latent, and reconstruct per-head keys and values at attention time via an up-projection. The cache stores one -dimensional vector per token rather than per token, where is the latent rank — typically much smaller. The arithmetic reconstruction at query time adds a bit of compute, but you can absorb that into the weight matrix with a carefully arranged matrix product, so the effective compute overhead is small.
Think of It Like This
A compressed zip archive you unpack on demand
Imagine storing a document's key highlights not as separate copies for 32 different readers, but as a single compact summary. When a reader arrives and asks a question, you unpack the summary into the specific excerpt that reader needs. The storage cost is the compact summary — much smaller than 32 separate copies.
MLA does exactly that for the KV cache. Every token compresses its K and V information into a small latent vector. At inference time, when a new query arrives, the latent is unpacked into the per-head keys and values that query needs. What persists in memory is the small latent, not the expanded tensors.
How It Actually Works
The two projections
For each token, MLA runs a down-projection that maps the token's hidden state to a low-rank latent , where :
This is what gets stored in the KV cache — one vector per token, per layer, with dimension .
At attention time, up-projections and reconstruct the per-head keys and values:
The full multi-head attention then proceeds as normal, using the reconstructed and .
The memory trade-off
Standard MHA caches floats per token. MLA caches floats. In DeepSeek-V2 with H=128, , and , that's a reduction from 32,768 floats to 512 — a 64× reduction in cache size over MHA. GQA with 8 groups on the same model would give a 16× reduction, so MLA is about 4× better than GQA here.
Absorbing the up-projection
The extra matmul at query time () would cost flops per head per query. But for the score computation , you can absorb into the query projection: compute once per head during prefill, then only the inner product with is needed at decode time. This keeps the per-step compute close to GQA's.
Show Me the Code
Verifying the cache size reduction and a single round-trip through the compression-and-reconstruction.
import numpy as np
rng = np.random.default_rng(0)
H, d_head, d_model, d_c = 8, 64, 512, 128 # small illustration
# Down-projection: x -> cW_down = rng.standard_normal((d_model, d_c)) * 0.02x = rng.standard_normal((d_model,))c = W_down.T @ x # shape: (d_c,)
# Up-projections: c -> K_h, V_h per headW_UK = rng.standard_normal((H, d_c, d_head)) * 0.02W_UV = rng.standard_normal((H, d_c, d_head)) * 0.02
K = np.einsum("hcd,c->hd", W_UK, c) # shape: (H, d_head)V = np.einsum("hcd,c->hd", W_UV, c) # shape: (H, d_head)
# Cache sizesstandard_cache = 2 * H * d_head # floats per tokenmla_cache = d_c # floats per token
print(f"Standard KV cache (per token): {standard_cache} floats")print(f"MLA latent cache (per token): {mla_cache} floats")print(f"Reduction: {standard_cache // mla_cache}×")# Standard KV cache (per token): 1024 floats# MLA latent cache (per token): 128 floats# Reduction: 8×print(f"K shape: {K.shape}, V shape: {V.shape}") # (8, 64) eachThe reconstruction is exact given the weight matrices — no approximation, unlike sparse or linear attention.
Watch Out For
Thinking MLA is an approximation
MLA does not approximate the attention scores the way sparse attention or linear attention does. Given the same weight matrices, the reconstructed K and V are exact. The compression happens in the cache — what you store between prefill and decode — not in the attention computation itself. The attention scores are exact; you're just computing them from a compressed representation.
Underestimating the training constraint
The down-projection and up-projections have to be learned together with the rest of the model. The latent rank is a design choice before training, and the model has to learn to encode useful K and V information into that rank budget. You can't retrofit MLA onto a trained MHA checkpoint the way you can partially uptrain GQA — the weight structure is fundamentally different.
The Quick Version
- MLA down-projects K and V into a shared low-rank latent before storing them; up-projections reconstruct per-head K and V at attention time.
- Cache size drops from to floats per token — a much larger reduction than GQA.
- The attention computation is exact, not an approximation — only the storage is compressed.
- The up-projection can be absorbed into the query projection to keep per-step compute low.
- MLA is a design choice made before training; it cannot be retrofitted to an existing MHA checkpoint.
What to Read Next
- Multi-Query Attention shares one KV pair across all heads — the simplest cache reduction and MLA's conceptual predecessor.
- Grouped-Query Attention groups heads into a small number of KV groups — the middle ground between MHA and MQA, and still the most common approach.
- Multi-Head Attention is the full-cache baseline MLA is designed to replace.
- Attention Complexity covers the quadratic cost that makes the KV cache a real memory constraint.
- KV Cache explains the caching mechanism these designs are all optimising.