APX AI
Online
When a transformer generates text autoregressively, it predicts the next token based on all previous tokens in the sequence. Recalculating the attention scores for the entire context at every step wastes massive amounts of computational resources. To prevent this, inference engines store the intermediate Key (K) and Value (V) matrices from earlier tokens in a memory buffer known as the KV cache. While this saves compute cycles, it trades processing time for raw memory capacity. As sequence lengths and concurrent batch sizes grow, the KV cache quickly becomes the primary memory bottleneck limiting physical hardware capacity.
Sizing the KV cache requires calculating the exact byte footprint of the stored tensors across the entire network. The required memory scales linearly with sequence length and batch size, governed by the specific architecture of the model.
The exact memory requirement for the KV cache is calculated using the following formula:
Where:
To see this in practice, calculate the KV cache requirement for a single 8192-token request running on meta-llama/Meta-Llama-3.1-8B at standard FP16 precision. The architecture defines 32 layers, 8 KV heads, and a head dimension of 128.
This equates exactly to 1.0 GiB per request. If you serve a batch of 16 concurrent users at this context length, the KV cache requires 16.0 GiB. Added to the ~15 GiB required to store the FP16 model weights, the total memory footprint reaches 31 GiB. This guarantees an Out of Memory (OOM) error on a standard 24GB RTX 3090 or RTX 4090 workstation. To fit this workload on a single consumer GPU, you must reduce the concurrent batch size, limit the maximum sequence length, or lower the precision of the cache.
KV cache memory scaling for meta-llama/Meta-Llama-3.1-8B across increasing context lengths and batch sizes using FP16 precision.
The primary architectural defense against exploding KV cache memory is Grouped-Query Attention (GQA). In older models using Multi-Head Attention (MHA), the number of KV heads matches the number of Query heads ().
If Llama 3.1 8B used MHA, it would have 32 KV heads instead of 8. Calculating the memory for that theoretical MHA design yields 4.0 GiB per request instead of 1.0 GiB. By reducing the number of KV heads, GQA shares one KV pair across multiple Query heads, immediately slashing the memory footprint by 75% or more depending on the ratio.
Memory allocation flow during autoregressive generation. Query vectors are transient and discarded after the attention matrix multiplication, while Key and Value vectors persist in VRAM for the duration of the request.
When sizing infrastructure for enterprise models, you must account for the cache required by extreme sequence lengths. For example, deploying Qwen/Qwen2.5-32B on a local server equipped with dual RTX 3090 24GB GPUs (48 GiB total VRAM).
First, we load the model weights using 4-bit AWQ quantization, which consumes approximately 18 GiB. This leaves 30 GiB of VRAM available across the two cards for the KV cache and context overhead.
The Qwen2.5-32B architecture features 64 layers, 8 KV heads, and a head dimension of 128. We want to calculate how many concurrent 8192-token requests we can support in FP16 precision.
Each request consumes exactly 2.0 GiB of KV cache. Dividing our 30 GiB of available VRAM by 2.0 GiB dictates a maximum theoretical batch size of 15 concurrent requests before the dual-GPU system runs out of memory.
To double or quadruple the maximum batch size on fixed hardware, inference frameworks like vLLM support quantizing the KV cache independently from the model weights. Storing the cached matrices in FP8 format reduces the multiplier from 2 to 1.
For example, the architecture of mistralai/Mixtral-8x7B-Instruct-v0.1, which contains 32 layers, 8 KV heads, and a head dimension of 128. Serving this sparse MoE model at a 32,768 context length in FP16 requires a massive KV cache allocation:
Serving just 16 users at maximum context length consumes ~68 GiB of VRAM for the cache alone. If you run this on a single 80GB node like an NVIDIA A100 or Apple Silicon M2 Ultra with 128GB of unified memory, the cache footprint competes heavily with the model weights. By enabling FP8 KV caching via vLLM (--kv-cache-dtype fp8), the footprint drops to 2.15 GiB per request. This optimization sacrifices a negligible amount of accuracy while directly doubling the serving throughput of the node.
To accurately plan hardware purchases, you must extract the correct topology values from the model before running sizing calculations. You can pull the exact layer counts and head configurations using the transformers library in Python.
import torch
from transformers import AutoModelForCausalLM
# Load the Qwen 2.5 7B model configuration
model_id = "Qwen/Qwen2.5-7B"
model = AutoModelForCausalLM.from_pretrained(
model_id,
torch_dtype=torch.float16,
device_map="cpu" # Load to CPU RAM just to inspect metadata
)
config = model.config
# Calculate the head dimension
head_dim = config.hidden_size // config.num_attention_heads
print(f"Total Layers: {config.num_hidden_layers}")
print(f"KV Heads: {config.num_key_value_heads}")
print(f"Head Dimension: {head_dim}")
# Calculate exact KV memory for a single token in bytes (FP16 = 2 bytes)
bytes_per_token = 2 * config.num_hidden_layers * config.num_key_value_heads * head_dim * 2
print(f"KV Memory per token: {bytes_per_token} bytes")
Running this script verifies the physical dimensions needed for your capacity equations, ensuring your deployment sizing maps accurately to the specific model you plan to put into production.
Wei-Ming Thor
• Founder & Engineer, ApX Machine Learning
Specializes in model architecture analysis and hardware capacity sizing for LLM infrastructure. Maintains the ApX VRAM Calculator.
© 2026 ApX Machine LearningContent Integrity & Transparency•