VRAM Calculation in Practice: Model Scale × Quantization, and How to Estimate KV Cache
VRAM Calculation in Practice: Model Scale × Quantization, and How to Estimate KV Cache
The previous article covered "choose a card by VRAM." This one opens up the math: why does the same model need several extra gigabytes at different context lengths? When "27B won't run," is the gap in weights or in KV cache? How do you size GPU offload layers? Once the formulas and measurement methods are clear, you can estimate accurately before buying and tune precisely after deploying.
The short version
VRAM = weights + KV cache + runtime overhead. Weights = parameter count × per-tier byte coefficient (Q4_K_M is about 0.6 bytes/param); KV cache grows linearly with context and dominates long-context scenarios; add another 1-2GB for runtime overhead. After it runs, calibrate with nvidia-smi and llama.cpp startup logs — that beats any formula.
Context length is the multiplier nobody budgets
The single most common planning error is computing VRAM for short contexts and then running long documents. KV cache at 8K may be manageable while the same model at 32K doubles your total requirement — and users discover this only when the first long document arrives.
Before buying, write down the longest realistic input your workload will send: whole codebases, full documents, long conversation histories. Size the card for that number, not for the demo prompt. If the honest answer is "sometimes very long," either budget for it or plan a documented fallback (summarize-then-process, chunking) rather than discovering the failure in production.
A quick estimation workflow
Pulling it together, here is the workflow to run before any purchase or deployment decision:
- Pick the target model and tier — for example, 27B at Q4_K_M.
- Compute weights from the table above, then confirm against the model card's actual file size.
- Estimate KV cache at your realistic context length and concurrency using the reference values, not your hopes.
- Add overhead of 1-2GB, then target 85-90% of the card's capacity — never 100%.
- Verify empirically once running: nvidia-smi for peaks, llama.cpp logs for KV cache, and a tokens-per-second benchmark at your real prompt length.
The gap between step 4 and step 5 is where most surprises live. Treating the formula as a first draft and the measurement as the truth is the whole discipline.
Formula one: weight size
Weight size = parameter count × bytes per parameter. Empirical coefficients per tier:
| Tier | Bytes/param (approx.) | 7B | 27B | 70B |
|---|---|---|---|---|
| Q8_0 | 1.05 | 7.4GB | 28GB | 74GB |
| Q6_K | 0.85 | 6.0GB | 23GB | 60GB |
| Q5_K_M | 0.72 | 5.0GB | 19GB | 50GB |
| Q4_K_M | 0.60 | 4.2GB | 16GB | 42GB |
| Q3_K_M | 0.48 | 3.4GB | 13GB | 34GB |
| Q2_K | 0.35 | 2.5GB | 9.5GB | 25GB |
Why approximately
Different models have different embedding and output layer sizes, so actual GGUF file sizes vary about 5%-10% at the same parameter count. Before buying a card, check the actual file size on the model card — more reliable than applying coefficients blindly.
Bandwidth matters as much as capacity
Two cards can hold the same model and deliver very different speeds. Generation speed (tokens per second) is dominated by memory bandwidth: the model weights are read for every token generated, so bandwidth sets the ceiling.
This changes purchase logic: a card with 24GB of slower memory often beats a card with 16GB of faster memory for local inference, because the constraint is usually capacity, not speed — while the opposite is true once capacity is satisfied and speed becomes the complaint.
A practical benchmark habit: before buying, run the exact model and tier you plan to use on a friend's machine, a rental, or a demo, and note tokens per second at your realistic context length. Spec sheets do not predict inference speed as reliably as one honest measurement.
Formula two: KV cache
KV cache stores the K/V matrices of historical tokens and is the hidden big-ticket item in long-context deployment. Per-request estimate:
KV cache ≈ 2 (K and V) × layers × total KV head dimension × context length × 2 bytes (fp16)
You do not need the exact formula — just two rules:
- Grows linearly with context — 8K to 32K means roughly 4x the KV cache
- Grows linearly with batch — 4 concurrent requests means roughly 4x the KV cache
Practical reference values (fp16, single request, for estimation only):
| Model scale | 8K context | 32K context |
|---|---|---|
| 7B class | ~0.5-1GB | ~2-4GB |
| 27B class | ~1-2GB | ~4-8GB |
| 70B class | ~2-4GB | ~8-16GB |
In long contexts, KV cache can exceed half the weights
A 27B model at Q4 has about 16GB of weights, while 32K-context KV cache can reach 4-8GB — a quarter to half of VRAM devoted to "remembering history." That is why the same 27B model feels smooth in short chats but OOMs on long documents. Plan long-context deployments with KV cache as a separate line item.
Formula three: runtime overhead
Framework overhead: CUDA context (~0.3-0.5GB), inference engine caches, memory fragmentation — budget another 1-2GB. With multiple GPUs, each card carries its own overhead.
Full worked examples
Case 1: Qwen3.8-27B, Q4_K_M, 8K context, single user
- Weights 16GB + KV cache ~1.5GB + overhead 2GB ≈ 19.5GB → a 24GB card runs it
Case 2: same, but 32K context
- Weights 16GB + KV cache ~6GB + overhead 2GB ≈ 24GB → a 24GB card sits right at the edge; 32GB or a lower tier is safer
Case 3: Hunyuan 4B (hy4), Q4_K_M, 8K context
- Weights ~2.5GB + KV cache ~0.5GB + overhead 2GB ≈ 5GB → runs easily on 8GB, acceptable even on CPU
MoE models calculate differently
For MoE like 35B-A3B: weights are sized by total 35B parameters (about 21GB at Q4), KV cache follows the actual architecture's layers/KV heads, and speed feels like the 3B active. So a MoE's VRAM need resembles a 35B dense model while its speed resembles a 3B model — exactly why it suits local deployment.
Sizing GPU offload layers
llama.cpp's -ngl (n_gpu_layers) decides how many layers live in VRAM versus RAM. Method:
- Try all layers: set
-nglto the total layer count (the startup log prints it) and see if it OOMs - Drop on OOM: reduce by 4-8 layers at a time until it loads
- Weigh the speed: more layers left in RAM means slower generation — benchmark tokens/s with the same prompt to find the "loads plus acceptable speed" balance
Offloading is not free
Once some layers live in RAM, every generated token crosses PCIe to move data, and speed can fall to a fraction of full-GPU. If you must offload more than half the layers, switching to a smaller model or a lower quantization tier gives a much better experience.
Calibrate by measurement — more accurate than formulas
Formulas estimate before buying; measurement tunes after deploying:
Watch VRAM usage: run nvidia-smi in another terminal and observe peak usage during inference.
Read the KV cache allocation: llama.cpp prints the actual KV cache allocation at startup (something like llama_kv_cache: ... MiB) — use it to calibrate your coefficients.
Check fragmentation: if peak usage runs 2GB+ above the formula, check whether you set -c (context) or batch parameters larger than needed.
# Watch the KV cache allocation in the logs when starting llama-server
./llama-server \
-m ./models/Qwen3.8-27B-Q4_K_M.gguf \
-ngl 40 \
-c 8192 \
--host 127.0.0.1 --port 8080
Batched inference multiplies VRAM
For multi-user local deployment: KV cache multiplies by concurrency. One user at 8K context uses ~1.5GB; four concurrent users use ~6GB — plus weights and overhead, a 24GB card running 27B with 4-way concurrency gets tight.
Strategy: cap concurrency (llama-server's parallel setting), reserve VRAM for it, or hand high-concurrency scenarios to a cloud API.
FAQ
Why is my VRAM usage above the formula?
Can KV cache be compressed?
27B at Q4_K_M or Q3_K_M?
What -ngl value should I use?
How do I size VRAM for MoE?
The formula lands exactly at the card's capacity — will it run?
Related reading
- Buying Local Compute: A GPU Purchase Guide — choosing a card by VRAM
- The Complete Local Deployment Playbook — hardware check to workflow integration
- Qwen KV Cache and Long Contexts — KV cache mechanics
- Qwen GGUF Local Deployment Primer — deployment basics
- Local Compute Cost Model — buy vs rent vs API