KV Cache Memory › Cache Size Calculation
Language AI HandbookAll chapters KV Cache Memory › Cache Size CalculationOne section · Sections in this chapter3 / 14 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
With a clear understanding of what the cache stores, we can now derive the formula for total memory consumption. The calculation follows directly from multiplying the dimensions of the cached tensors by the number of bytes each element requires. There is no approximation involved: this is exact arithmetic about the shape of the tensors sitting in your GPU's memory. This derivation provides the basis for all deployment planning decisions, and once you work through it once, you will be able to estimate cache sizes in your head for any model architecture.
Consider the structure we described above. For each layer, we store both keys and values. Each of these has shape [batch_size, num_kv_heads, seq_len, head_dim]. The total number of elements in one such tensor is the product of these dimensions. Since we store two tensors (keys and values) per layer across all layers, the total element count becomes:
Converting elements to bytes requires multiplying by the bytes per element, giving us the complete formula:
where:
- accounts for storing both key and value matrices
- : the number of transformer layers
- : the batch size (number of concurrent sequences)
- : the sequence length (number of tokens cached)
- : the number of key-value heads
- : the head dimension (dimensionality of each attention head)
- : the number of bytes per element (2 for FP16/BF16, 4 for FP32)
The key insight is that every term in this product is linear: there are no squares, no logarithms, no nonlinear interactions. Doubling any single factor doubles the memory. This linearity makes the formula both simple to use and relentlessly demanding in practice. You cannot cleverly reorganize the computation to escape the cost. Every factor must be paid in full.
This formula reveals the linear dependencies that govern cache memory. Doubling any of the multiplicative factors doubles the total memory. This linearity is both a blessing and a curse. It makes calculations simple and predictable, but it also means there are no economies of scale. Processing twice as many tokens always requires twice as much cache memory, with no possibility of compression through clever algorithms unless we explicitly introduce approximation techniques, which we cover in later chapters on cache quantization and pruning.
Standard Multi-Head Attention
For standard Multi-Head Attention (MHA), equals the number of attention heads , and the relationship holds. This relationship exists because each head operates on a slice of the model dimension, and together all heads span the full representation space. This architectural constraint allows us to substitute and simplify our formula:
where:
- : the model dimension (equal to , the full embedding size)
- : the number of transformer layers
- : the batch size
- : the sequence length
- : the number of bytes per element
This simplified form is particularly useful because is the first number reported in any model card or architecture description. Knowing that a model has dimension 4096, 32 layers, and you want to cache 4096 tokens in FP16, you can quickly compute:
This mental arithmetic takes seconds and immediately tells you whether your hardware can support a given configuration.
Grouped Query Attention and Cache Reduction
For models using Grouped Query Attention (GQA), which we covered in the Modern Decoder Models section, the number of KV heads is smaller than the number of query heads. This architectural innovation allows multiple query heads to share the same key-value pairs, dramatically reducing the cache footprint. GQA achieves this reduction without proportionally harming model quality, making it one of the most impactful architectural changes for inference efficiency introduced in recent years.
To understand why GQA reduces cache size, consider what the cache stores. In standard MHA, every query head has its own dedicated key head and value head. A model with 64 query heads caches 64 sets of keys and 64 sets of values. In GQA with 8 KV heads, 8 groups of 8 query heads each share one set of keys and one set of values. The cache stores only 8 sets of keys and 8 sets of values, but all 64 query heads can still attend to their relevant context. The queries are still diverse and specialized; only the cached targets are shared.
If a model has query heads but only key-value heads, the cache size reduces proportionally:
where:
- : the number of query attention heads (used for computation but not cached)
- : the number of key-value heads (the only heads whose projections are cached)
This reduction factor quantifies the memory savings from GQA. A model with 64 query heads and 8 KV heads achieves an 8-fold reduction in cache size compared to standard MHA. This 8-fold reduction can mean the difference between a model that requires multiple GPUs to deploy and one that fits on a single high-end card. The practical impact of GQA on deployment feasibility cannot be overstated.
Think of GQA as a shared note-taking system in a large meeting. In standard MHA, each participant (query head) takes their own complete notes (keys and values) about what everyone said. In GQA, one designated note-taker serves each small group of participants, and everyone in the group reads from the same set of notes. The quality of the discussion suffers only marginally because the notes are still detailed. But the storage cost falls by the number of participants per group.
Now let's examine concrete examples with popular model architectures. First, we define our model specifications and a calculation function:
def calculate_kv_cache_memory(
num_layers: int,
num_kv_heads: int,
head_dim: int,
batch_size: int = 1,
seq_len: int = 2048,
dtype_bytes: int = 2, # FP16 default
) -> dict:
"""
Calculate KV cache memory requirements.
Returns memory in bytes, MB, and GB.
"""
# Total elements: 2 (K+V) × layers × batch × seq × heads × head_dim
total_elements = (
2 * num_layers * batch_size * seq_len * num_kv_heads * head_dim
)
# Convert to bytes
memory_bytes = total_elements * dtype_bytes
memory_mb = memory_bytes / (1024**2)
memory_gb = memory_bytes / (1024**3)
return {
"elements": total_elements,
"bytes": memory_bytes,
"MB": memory_mb,
"GB": memory_gb,
}
# Model specifications
models = {
"GPT-2 (124M)": {
"num_layers": 12,
"num_kv_heads": 12,
"head_dim": 64,
"d_model": 768,
"total_params": 124_000_000,
},
"LLaMA 7B": {
"num_layers": 32,
"num_kv_heads": 32, # MHA
"head_dim": 128,
"d_model": 4096,
"total_params": 7_000_000_000,
},
"LLaMA 2 70B": {
"num_layers": 80,
"num_kv_heads": 8, # GQA with 8 KV heads
"head_dim": 128,
"d_model": 8192,
"total_params": 70_000_000_000,
},
"LLaMA 3 70B": {
"num_layers": 80,
"num_kv_heads": 8, # GQA
"head_dim": 128,
"d_model": 8192,
"total_params": 70_000_000_000,
},
}model_results = {}
for model_name, specs in models.items():
cache = calculate_kv_cache_memory(
num_layers=specs["num_layers"],
num_kv_heads=specs["num_kv_heads"],
head_dim=specs["head_dim"],
batch_size=1,
seq_len=4096,
dtype_bytes=2,
)
weight_gb = specs["total_params"] * 2 / (1024**3)
cache_pct = (cache["GB"] / weight_gb) * 100
model_results[model_name] = {
"weight_gb": weight_gb,
"cache_gb": cache["GB"],
"cache_pct": cache_pct,
}GPT-2 (124M): Model weights: 0.2 GB KV cache: 0.14 GB (60.9% of weights) LLaMA 7B: Model weights: 13.0 GB KV cache: 2.00 GB (15.3% of weights) LLaMA 2 70B: Model weights: 130.4 GB KV cache: 1.25 GB (1.0% of weights) LLaMA 3 70B: Model weights: 130.4 GB KV cache: 1.25 GB (1.0% of weights)

These results reveal several important patterns about KV cache scaling across different architectures. For GPT-2, the cache remains negligible relative to model weights, consuming only about 2-3% of total memory. This makes sense: GPT-2 was designed before long-context inference became a priority, and its small embedding dimension (768) and modest layer count (12) mean the cache grows slowly. As we scale to larger models like LLaMA 7B, the cache becomes more significant, reaching approximately 7-8% of weight memory at 4K context.
The most striking pattern appears with LLaMA 2 and 3 70B models. Despite being 10 times larger than LLaMA 7B by parameter count, their use of Grouped Query Attention with only 8 KV heads means their cache is smaller than LLaMA 7B's cache. This shows an 8-fold reduction compared to what standard multi-head attention would require. This architectural choice makes the difference between practical deployment and memory constraints that would force a multi-GPU cluster. GQA made 70B-parameter models deployable on a single A100 GPU.