Account for weights, workspace, and the KV state actually resident on each rank
Calculate layer, head, token, and dtype contributions while separating GQA savings, tensor-parallel partitioning, replication, and non-KV memory peaks.
On this page
The question for today
What you’ll understand
- Calculate dense KV payload from layers, KV heads, head width, tokens, and element bytes.
- Distinguish query heads from KV heads and per-rank shards from replicated heads.
- Separate payload accounting from allocator, workspace, and driver-level memory bounds.
A model's weight file is only one part of an inference worker's memory footprint. Autoregressive requests retain attention keys and values, kernels need temporary workspace, and the runtime owns additional buffers and allocator capacity. A useful budget names each category and its measurement boundary. Start with an exact count for a specified tensor layout, then add implementation overhead and observed peaks; do not turn a tidy payload formula into a claim that every request with that token count will fit.
Count the retained representation rather than the model's marketing size
For a conventional dense decoder with equal key and value widths, each retained token contributes a key and a value at every attention layer. Multiply the number of layers by local KV heads, head width, element bytes, and the number of retained token positions. Grouped-query attention has fewer KV heads than query heads; substituting query-head count overestimates that particular payload. Architectures with different key/value widths, sliding windows, compressed latent states, or unequal layers require their own sum rather than this simplified product. Specify the architecture and cache dtype independently of the weight dtype.
A parameter estimate similarly multiplies stored elements by bytes only when the format is truly uniform and unpacked. Quantized weights can add scales, zero points, padding, and special full-precision tensors. In ordinary inference there is no reason to automatically add training optimizer states, but an accidental gradient graph or retained activation can still consume memory. Include logits, attention workspace, communication buffers, CUDA graph pools, and runtime allocations where applicable. Prefill and decode can have different peaks, so observing a quiet decode iteration does not bound the memory required to admit a new long prompt.
Tensor parallelism does not always divide KV storage by the rank count
When KV heads divide evenly across tensor-parallel ranks, each rank can retain its head shard. Once the rank count exceeds the number of KV heads, an implementation may replicate heads rather than store fractional heads. The tagged vLLM 0.9.1 Llama attention code explicitly partitions in the former case and replicates in the latter, with divisibility checks. For example, eight KV heads across sixteen ranks leave one resident KV head per rank in that implementation, not half a head; aggregate storage is then twice the unreplicated payload.
Pipeline placement, replicated embeddings, communication workspaces, and uneven layer assignment can further change per-rank peaks. Compute the budget for the busiest rank, not just total cluster memory divided by worker count. A shared prompt also has a logical token count larger than its unique physical KV storage when correctly reused, while incompatible prefixes cannot be merged merely because token lengths match. Record the exact rank topology, model revision, dtype, and implementation version with a memory estimate so later capacity measurements can be compared against the same assumptions.
Validate the memory budget at the execution boundary
Compare predicted payload growth with measured allocated memory, pool occupancy, and device-level usage while controlling batch shape and prefix sharing. Differences can reveal block rounding, replicated heads, cached workspaces, or allocations outside the framework profiler. Leave explicit headroom for transient peaks and concurrent work. A measured average is not an admission invariant, and a bandwidth-limited decode kernel can still fail because capacity is exhausted. Keep capacity in bytes separate from throughput in bytes per second or floating-point operations per second.
The roofline lab isolates that final distinction. Reset, explicitly set BOTH intensity I=8 and bandwidth B=80, predict a ceiling of 640 GFLOP/s, then Play or Step. Reset and re-set BOTH I=8 and B=160; predict the fixed 1000-GFLOP/s compute cap. Edits retain t; playback traces the roof without changing the selected kernel. B uses decimal GB/s. This synthetic ceiling has no model tensors, KV heads, devices, or allocator, and it cannot determine whether either configuration has enough memory to hold one request.
Work it through
Count a GQA cache and its four-rank shard
Assume a dense decoder has 32 layers, eight KV heads, head width 128, and two bytes per key or value element. One unshared request retains 2048 tokens. Four tensor-parallel ranks evenly partition the eight KV heads; ignore padding and metadata.
The unsharded payload per token is 2×32×8×128×2=131072 bytes, or 128 KiB. Query-head count is irrelevant to this retained-KV calculation.
For 2048 tokens, payload is 131072×2048=268435456 bytes, or 256 MiB. This counts only the specified key and value tensors.
Each of four ranks holds two KV heads, so its payload is 256/4=64 MiB. Add each rank's weights, workspace, block rounding, and other allocations separately before making a fit decision.
The exact simplified KV payload is 256 MiB overall and 64 MiB per rank, while total inference memory remains a larger implementation-dependent budget.
The living notebook
Explore the model
Interactive lab · roofline
Bandwidth capacity and memory capacity are different budgets
For EACH run Reset, set BOTH I and B, predict, then Play or Step. At I=8 FLOP/byte, B=80 decimal GB/s gives ceiling 640 GFLOP/s; B=160 reaches the fixed 1000 cap. Edits retain t. This synthetic throughput ceiling does not count weights, KV tensors, allocator bytes, or device capacity.
- Attainable ceiling
- 640 GFLOP/s
- Ridge intensity
- 12.5 FLOP/byte
- Ceiling regime
- Memory-bound ceiling
Synthetic roofline ceiling min(1000, B·I), in GFLOP/s, with B in decimal GB/s and I in FLOP/byte. Playback traces the roof without changing the selected kernel. This upper-bound model is not a measured throughput prediction, hardware comparison or price model. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.
Look forA throughput bound cannot replace byte accounting or a measured peak-memory budget.
Pause & reason
Check your understanding
Your turn
Try it yourself
A homogeneous dense cache has sixteen layers, four KV heads, head width 64, one byte per scalar, and 1024 unshared retained tokens. Calculate its payload. Why is this not a full worker-memory bound?
Take a moment to make a prediction or work it out on paper. Open a hint when you need one.
Give me a hint
Count both keys and values, then convert bytes using one MiB=1048576 bytes.
Compare with the solution
Payload is 2×16×4×64×1×1024=8388608 bytes, or eight MiB. The calculation excludes weights, block rounding, quantization metadata if present, runtime buffers, workspace, and device allocations outside this cache, so it does not bound the worker's total peak.
Keep the idea
Take it with you
- KV payload depends on resident KV heads, layers, width, retained positions, and cache dtype.
- Tensor-parallel KV replication can prevent memory from scaling inversely with rank count.
- Payload identities, observed memory, admission bounds, and bandwidth ceilings answer different questions.
Read further
Original sources and deeper explanations to follow at your own pace.
Optional progress, saved in this browser when available. Revisit any lesson at any time.
Lesson not marked complete.