How the numbers are made
Every estimate in the calculator comes from one plain TypeScript model, engine.ts, which runs in your browser. This page writes out its formulas, the constants they use and the published measurements the speed constants are fitted to.
Contents
Overview
Memory is counted part by part: weights, KV cache, activations, runtime overhead and, when used, a speculative drafter. Speed follows from the hardware: generating a token means reading the weights and the KV cache from memory, so decode is limited by memory bandwidth; reading a prompt is a large matrix multiplication, so prompt processing is limited by compute. Fixed costs per step and per layer (kernel launches, scheduling) are added on top.
How close a runtime gets to the hardware's peak depends on the runtime and the GPU, so those efficiencies are fitted to 123 published measurements. The results are estimates. Drivers, kernels, settings and the prompts you send all move real numbers.
Model shape
Each model is described by its Hugging Face config.json: layers L, hidden size h, attention heads nh, KV heads nkv, head size dh, feed-forward size dff, vocabulary V, and the parameter count P from the model's published weights. Hybrid models also give the number of sliding-window layers (window w), linear-attention or state-space layers, and Multi-head Latent Attention (MLA) models give the size of their compressed KV latent.
For a mixture-of-experts (MoE) model with E experts and k active per token, the parameters used per token Pactive come from the model card when published, and otherwise from:
Memory
Weights
Weights take their bits per weight b. GGUF figures are whole-file averages, which already include the embeddings. Other quantized formats keep the embeddings and output head (Pemb = V·h, twice when they aren't tied) in 16-bit:
| Format | Bits per weight |
|---|---|
| FP16 / BF16 | 16 |
| FP8 | 8 |
| INT8 | 8.1 |
| GGUF Q8_0 | 8.5 |
| NVFP6 | 6.5 |
| GGUF Q6_K | 6.56 |
| GGUF Q5_K_M | 5.7 |
| GGUF Q4_K_M | 4.85 |
| GGUF Q4_0 | 4.54 |
| NVFP4 | 4.5 |
| INT4 (bitsandbytes) | 4.5 |
| EXL2 | 4.5 |
| MXFP4 | 4.25 |
| AWQ / GPTQ | 4.25 |
| GGUF Q3_K_M | 3.91 |
| GGUF Q2_K | 3 |
KV cache
Each sequence of s tokens stores keys and values in every attention layer:
- c
- values per token per layer: 2 × nkv × dh, or the latent size for MLA (576 by default)
- β
- bytes per value: 2 for FP16/BF16, 1 for FP8 and INT8, 0.5 for INT4
- S
- the fixed recurrent state of a linear-attention or state-space layer, whatever the length
One copy of the model serves nseq = ⌈users / copies⌉ × batch sequences at once. With prefix caching, the shared share f of the prompt is stored once: KV(s) × (nseq × (1 − f) + f). Tensor parallelism over tp GPUs splits the KV heads, so each GPU keeps ⌈nkv / tp⌉ / nkv of the cache (MLA latents are copied to every GPU). Pipeline parallelism over pp stages divides it by pp.
Activations and runtime overhead
Runtimes process prompts in chunks of C tokens (8,192 for vLLM, 512 for llama.cpp), and keep the logits of every running sequence:
Without fused (flash) attention, llama.cpp, Ollama and Transformers materialize the score matrix of a chunk in FP32, C × s × nh × 4 bytes. Each runtime also holds a fixed amount for its CUDA context, graphs and buffers, plus 0.5 GB when a copy spans several GPUs.
Speculative decoding drafters
A draft model adds its parameters in BF16. Learned drafters are sized from the target model, with one transformer layer counted as 12h² parameters: an EAGLE-3 head is one layer plus a 32K-token output head (12h² + 32,000h), a DFlash drafter about five layers, and multi-token prediction (MTP) one extra layer at the model's own precision. N-gram and suffix lookup add nothing.
Usable memory and verdict
Per GPU, the total is W × (1 − o) / (tp × pp) plus the KV cache, activations, scores, overhead and drafter, where o is the share of weights offloaded to CPU memory (offloading the KV cache keeps 30% of it on the GPU). It is compared with the memory the runtime lets itself use. Apple Silicon can only wire about 75% of unified memory to the GPU, two thirds on machines with 36 GB or less.
| Runtime | Memory it uses | Fixed overhead | Prompt chunk |
|---|---|---|---|
| vLLM | 90% | 1.5 GB | 8,192 |
| SGLang | 88% | 1.5 GB | 8,192 |
| TensorRT-LLM | 90% | 1.2 GB | 8,192 |
| llama.cpp | 100% | 0.4 GB | 512 |
| Ollama | 100% | 0.5 GB | 512 |
| Transformers | 100% | 0.8 GB | 4,096 |
| Other | 90% | 1 GB | 4,096 |
Below 50% of usable memory the setup is comfortable, then moderate up to 75%, high up to 90%, very high up to 100%, and it doesn't fit beyond. The number of users that fit is the memory left after everything but the KV cache, divided by the KV cache of one user, times the number of copies.
Decode speed
Each decode step produces one token for each of the b sequences in flight. Its time is the larger of reading memory and computing, plus communication and fixed costs:
- B
- the GPU's memory bandwidth from its spec sheet
- η
- the share of it the runtime achieves (fitted, see Calibration)
- F
- dense FP16/BF16 tensor throughput with FP32 accumulate
- tstep, tlayer
- fixed cost per step and per layer (launches, scheduling); MoE layers add routing and small expert matmuls
Wread is the weights streamed per step. The input embedding table is only looked up, so it isn't streamed when it is separate from the output head. An MoE model always reads its shared weights, plus the experts the batch touches. With b tokens each picking k of E experts, the expected number touched is:
Weights and KV cache offloaded to the CPU are read at 60 GB/s (dual-channel DDR5), which adds tcpu.
Several GPUs
Tensor parallelism splits every layer across tp GPUs, which then all-reduce activations twice per layer. An all-reduce of x bytes over n GPUs costs a latency term plus the ring algorithm's traffic:
So ttp = 2L × AR(2bh, tp). Pipeline parallelism passes activations between pp stages: tpp = (pp − 1) × AR(2bh, 2). Tensor parallelism that spans machines uses the network between them.
| Link | Bandwidth per direction | Latency λ |
|---|---|---|
| NVLink 5 | 900 GB/s | 5 µs |
| NVLink 4 | 450 GB/s | 6 µs |
| NVLink 3 | 300 GB/s | 7 µs |
| PCIe 5 | 64 GB/s | 15 µs |
| PCIe 4 | 32 GB/s | 20 µs |
| InfiniBand NDR | 50 GB/s | 15 µs |
| InfiniBand HDR | 25 GB/s | 18 µs |
| 400G Ethernet | 50 GB/s | 25 µs |
| 100G Ethernet | 12.5 GB/s | 30 µs |
| 10G Ethernet | 1.25 GB/s | 60 µs |
| Thunderbolt 5 | 10 GB/s | 40 µs |
Several copies of a model (replicas) each get tp × pp GPUs and split the users between them. Per-user speed is 1 / t(b); total throughput is that speed times the sequences in flight times the copies. Requests per second assume 512 output tokens per request.
Speculative decoding
A drafter proposes k tokens and the model checks them in one step over k + 1 tokens per sequence, so that step is t(b) with b(k + 1) tokens: more compute and, for MoE models, more experts touched. With acceptance rate a per drafted token, a step yields on average (1 − ak+1) / (1 − a) tokens (Leviathan et al.). Drafting takes its own time: each pass reads the drafter and runs its layers, tdraft = passes × (bytes read / (tp × B × η) + layers × tlayer). Draft models, EAGLE-3 heads and MTP make one pass per drafted token, DFlash one pass for the whole block; MTP and DFlash also run the model's output head, which is large for big vocabularies. N-gram and suffix lookup take no GPU time. Verifying costs about 3% more per drafted token (rejection sampling, KV writes):
Measured gains shrink with the batch size faster than this, as kernels don't overlap compute and memory perfectly, so the speedup used is 1 + (g − 1) / (1 + b / 8). vLLM reports an acceptance length (tokens per step); the calculator's acceptance rate is the a that gives the same length. The rates it suggests (from 0.4 for n-gram lookup to 0.85 for MTP) are typical values; yours depend on the model and the prompts.
Prompt processing
Reading an s-token prompt costs 2Pactive FLOPs per token plus attention, which grows with the square of the length:
Time to first token is the larger of that compute and re-reading the weights once per chunk, plus communication and a fixed cost:
- φ
- 1.6 for FP8 weights on GPUs with FP8 tensor cores, 2.4 for NVFP4 and MXFP4 on FP4 GPUs, otherwise 1
- μ
- the share of peak compute the runtime achieves on prompts (fitted)
- t0
- scheduling, tokenization and sampling: 15 ms unless fitted
Calibration
The efficiencies η, μ, tlayer and t0 start from typical values per runtime. Where published measurements exist, they are fitted to them by scripts/fit-speed.ts. The fit minimizes the squared log error, so being 2× too fast costs as much as being 2× too slow. It runs first over all GPUs of a runtime, then per GPU class (vendor plus consumer, workstation or datacenter), but only for a class with more GPUs than constants to fit. That matters: on prompts, llama.cpp reaches about 1.2× the catalog's FP16 figure on GeForce cards (its integer kernels beat the half-rate figure GeForce cards are rated at), about 0.5× on NVIDIA workstation cards and 0.15× to 0.3× on datacenter GPUs. Ollama runs llama.cpp and uses its constants.
| Runtime | GPUs | Bandwidth η | Per layer | Prompt μ | Fixed t₀ |
|---|---|---|---|---|---|
| llama.cpp | All GPUs | 92% | 57 µs | 61% | |
| llama.cpp | NVIDIA consumer | 85% | 12.5 µs | 121% | |
| llama.cpp | NVIDIA workstation | 82% | 12.5 µs | 48% | |
| llama.cpp | NVIDIA datacenter | 75% | 46.9 µs | 31% | |
| llama.cpp | AMD datacenter | 15% | |||
| llama.cpp | AMD consumer | 77% | 37.4 µs | 39% | |
| llama.cpp | AMD workstation | 50% | |||
| llama.cpp | Apple | 93% | 79.5 µs | 74% | |
| TensorRT-LLM | All GPUs | 93% | 50.6 µs | 72% | 4.59 ms |
| vLLM | All GPUs | 76% | 50.1 µs | ||
| vLLM | AMD datacenter | 58% | 0.38 µs |
Empty cells use the runtime's All GPUs line. Runtimes without measurements here (SGLang, Transformers) keep the starting values:
| Runtime | Bandwidth η | Per step | Per layer | Per MoE layer | Prompt μ |
|---|---|---|---|---|---|
| vLLM | 72% | 0.6 ms | 4 µs | +50 µs | 45% |
| SGLang | 74% | 0.5 ms | 4 µs | +40 µs | 45% |
| TensorRT-LLM | 78% | 0.4 ms | 3 µs | +35 µs | 55% |
| llama.cpp | 75% | 0.5 ms | 8 µs | +50 µs | 70% |
| Ollama | 72% | 1 ms | 10 µs | +55 µs | 65% |
| Transformers | 50% | 5 ms | 60 µs | +150 µs | 30% |
| Other | 70% | 1 ms | 10 µs | +60 µs | 40% |
Accuracy
Typical error is exp(mean |log(predicted / measured)|) − 1, so 10% means predictions are usually within about 10%. The figures below are on the measurements used for the fit. On a GPU left out of the fit, which is what a GPU without measurements gets, decode speed is typically within 10% and llama.cpp prompt processing within 25%.
| Runtime | Measurement | Benchmarks | GPUs | Typical error |
|---|---|---|---|---|
| vLLM | Decode speed | 7 | 6 | 6% |
| TensorRT-LLM | Decode speed | 6 | 4 | 6% |
| TensorRT-LLM | Time to first token | 4 | 3 | 2% |
| llama.cpp | Decode speed | 53 | 48 | 8% |
| llama.cpp | Prompt processing | 53 | 48 | 17% |
All 123 benchmarks, measured and predicted
| GPU | Model | Runtime | Measurement | Measured | Predicted | Off by | Source |
|---|---|---|---|---|---|---|---|
| RTX 5090 (32GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 300 | 292 | -3% | llama.cpp #15013 |
| RTX 5090 (32GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 14,970 | 18,286 | +22% | llama.cpp #15013 |
| RTX PRO 6000 Blackwell (96GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 281 | 286 | +2% | llama.cpp #15013 |
| RTX PRO 6000 Blackwell (96GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 16,619 | 17,655 | +6% | llama.cpp #15013 |
| H100 SXM (80GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 281 | 285 | +1% | llama.cpp #15013 |
| H100 SXM (80GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 11,263 | 22,261 | +98% | llama.cpp #15013 |
| A100 SXM (80GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 201 | 223 | +11% | llama.cpp #15013 |
| A100 SXM (80GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 5,286 | 7,111 | +35% | llama.cpp #15013 |
| RTX 4090 (24GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 189 | 186 | -2% | llama.cpp #15013 |
| RTX 4090 (24GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 14,771 | 14,629 | -1% | llama.cpp #15013 |
| RTX 5080 (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 185 | 178 | -3% | llama.cpp #15013 |
| RTX 5080 (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 9,488 | 10,039 | +6% | llama.cpp #15013 |
| RTX 5070 Ti (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 182 | 168 | -8% | llama.cpp #15013 |
| RTX 5070 Ti (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 8,420 | 7,877 | -6% | llama.cpp #15013 |
| RTX 6000 Ada (48GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 179 | 174 | -3% | llama.cpp #15013 |
| RTX 6000 Ada (48GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 10,577 | 12,800 | +21% | llama.cpp #15013 |
| RTX 3090 Ti (24GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 172 | 186 | +8% | llama.cpp #15013 |
| RTX 3090 Ti (24GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 6,924 | 7,111 | +3% | llama.cpp #15013 |
| RTX PRO 4500 Blackwell (32GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 169 | 164 | -3% | llama.cpp #15013 |
| RTX PRO 4500 Blackwell (32GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 7,252 | 7,111 | -2% | llama.cpp #15013 |
| RTX 3090 (24GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 162 | 175 | +8% | llama.cpp #15013 |
| RTX 3090 (24GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 5,560 | 6,321 | +14% | llama.cpp #15013 |
| L40 (48GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 154 | 127 | -17% | llama.cpp #15013 |
| L40 (48GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 10,098 | 4,163 | -59% | llama.cpp #15013 |
| RTX 4080 SUPER (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 147 | 142 | -4% | llama.cpp #15013 |
| RTX 4080 SUPER (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 9,439 | 9,309 | -1% | llama.cpp #15013 |
| RTX 4080 (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 143 | 139 | -3% | llama.cpp #15013 |
| RTX 4080 (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 9,206 | 8,678 | -6% | llama.cpp #15013 |
| RTX A6000 (48GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 145 | 144 | -1% | llama.cpp #15013 |
| RTX A6000 (48GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 5,662 | 5,505 | -3% | llama.cpp #15013 |
| RTX 3080 (10GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 140 | 146 | +4% | llama.cpp #15013 |
| RTX 3080 (10GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 5,570 | 5,333 | -4% | llama.cpp #15013 |
| RTX PRO 4000 Blackwell (24GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 136 | 128 | -6% | llama.cpp #15013 |
| RTX PRO 4000 Blackwell (24GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 5,674 | 5,333 | -6% | llama.cpp #15013 |
| RTX A5000 (24GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 136 | 144 | +6% | llama.cpp #15013 |
| RTX A5000 (24GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 4,552 | 3,938 | -13% | llama.cpp #15013 |
| V100 (32GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 135 | 131 | -3% | llama.cpp #15013 |
| V100 (32GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 2,974 | 2,860 | -4% | llama.cpp #15013 |
| RTX 4070 Ti SUPER (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 133 | 131 | -1% | llama.cpp #15013 |
| RTX 4070 Ti SUPER (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 7,612 | 7,877 | +3% | llama.cpp #15013 |
| RTX 5070 (12GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 128 | 131 | +2% | llama.cpp #15013 |
| RTX 5070 (12GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 5,783 | 5,505 | -5% | llama.cpp #15013 |
| A40 (48GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 126 | 108 | -15% | llama.cpp #15013 |
| A40 (48GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 5,256 | 3,436 | -35% | llama.cpp #15013 |
| A30 (24GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 132 | 135 | +2% | llama.cpp #15013 |
| A30 (24GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 3,069 | 3,793 | +24% | llama.cpp #15013 |
| RTX 2080 Ti (11GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 109 | 121 | +11% | llama.cpp #15013 |
| RTX 2080 Ti (11GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 3,108 | 2,404 | -23% | llama.cpp #15013 |
| RTX 5060 Ti (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 93.5 | 91.0 | -3% | llama.cpp #15013 |
| RTX 5060 Ti (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 4,196 | 4,163 | -1% | llama.cpp #15013 |
| RTX A4000 (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 85.2 | 88.5 | +4% | llama.cpp #15013 |
| RTX A4000 (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 2,808 | 2,738 | -2% | llama.cpp #15013 |
| RTX 3060 (12GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 76.9 | 74.4 | -3% | llama.cpp #15013 |
| RTX 3060 (12GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 2,408 | 2,226 | -8% | llama.cpp #15013 |
| RTX 4060 Ti (8GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 64.0 | 60.3 | -6% | llama.cpp #15013 |
| RTX 4060 Ti (8GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 3,803 | 3,908 | +3% | llama.cpp #15013 |
| RTX 4000 Ada (20GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 61.4 | 72.2 | +18% | llama.cpp #15013 |
| RTX 4000 Ada (20GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 3,172 | 3,793 | +20% | llama.cpp #15013 |
| DGX Spark GB10 (128GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 56.7 | 55.6 | -2% | llama.cpp #15013 |
| DGX Spark GB10 (128GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 3,661 | 3,556 | -3% | llama.cpp #15013 |
| RTX 2000 Ada (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 50.7 | 46.1 | -9% | llama.cpp #15013 |
| RTX 2000 Ada (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 2,250 | 1,707 | -24% | llama.cpp #15013 |
| T4 (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 44.0 | 56.1 | +27% | llama.cpp #15013 |
| T4 (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 1,310 | 1,488 | +14% | llama.cpp #15013 |
| Instinct MI300X (192GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 219 | 322 | +47% | llama.cpp #15021 |
| Instinct MI300X (192GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 11,946 | 14,629 | +22% | llama.cpp #15021 |
| RX 7900 XTX (24GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 170 | 146 | -14% | llama.cpp #15021 |
| RX 7900 XTX (24GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 3,874 | 3,507 | -9% | llama.cpp #15021 |
| Instinct MI210 (64GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 130 | 205 | +58% | llama.cpp #15021 |
| Instinct MI210 (64GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 2,572 | 2,048 | -20% | llama.cpp #15021 |
| Radeon PRO W7900 (48GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 127 | 140 | +10% | llama.cpp #15021 |
| Radeon PRO W7900 (48GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 3,473 | 4,491 | +29% | llama.cpp #15021 |
| RX 9070 (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 115 | 106 | -8% | llama.cpp #15021 |
| RX 9070 (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 2,453 | 2,048 | -16% | llama.cpp #15021 |
| RX 7900 XT (20GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 112 | 127 | +13% | llama.cpp #15021 |
| RX 7900 XT (20GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 3,262 | 2,926 | -10% | llama.cpp #15021 |
| Radeon AI PRO R9700 (32GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 98.0 | 113 | +16% | llama.cpp #15021 |
| Radeon AI PRO R9700 (32GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 4,773 | 3,556 | -26% | llama.cpp #15021 |
| RX 7900 GRE (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 97.5 | 97.0 | -1% | llama.cpp #15021 |
| RX 7900 GRE (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 1,599 | 2,612 | +63% | llama.cpp #15021 |
| RX 9070 XT (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 97.3 | 106 | +9% | llama.cpp #15021 |
| RX 9070 XT (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 4,904 | 2,753 | -44% | llama.cpp #15021 |
| RX 7800 XT (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 96.0 | 104 | +8% | llama.cpp #15021 |
| RX 7800 XT (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 2,305 | 2,107 | -9% | llama.cpp #15021 |
| RX 9060 XT (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 65.4 | 58.2 | -11% | llama.cpp #15021 |
| RX 9060 XT (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 1,479 | 1,450 | -2% | llama.cpp #15021 |
| Ryzen AI Max+ 395 (96GB of 128GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 49.9 | 47.5 | -5% | llama.cpp #15021 |
| Ryzen AI Max+ 395 (96GB of 128GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 1,004 | 1,679 | +67% | llama.cpp #15021 |
| RX 7600 XT (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 47.6 | 52.9 | +11% | llama.cpp #15021 |
| RX 7600 XT (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 1,199 | 1,280 | +7% | llama.cpp #15021 |
| M1 Ultra (128GB) | Llama-2-7b-hf FP16 | llama.cpp | Decode speed, 128 tokens | 47.8 | 47.7 | 0% | llama.cpp #4167 |
| M1 Ultra (128GB) | Llama-2-7b-hf FP16 | llama.cpp | Prompt processing, 512 tokens | 1,294 | 1,138 | -12% | llama.cpp #4167 |
| M1 Ultra (128GB) | Llama-2-7b-hf Q8_0 | llama.cpp | Decode speed, 128 tokens | 79.1 | 79.3 | +0% | llama.cpp #4167 |
| M1 Ultra (128GB) | Llama-2-7b-hf Q8_0 | llama.cpp | Prompt processing, 512 tokens | 1,168 | 1,138 | -3% | llama.cpp #4167 |
| M1 Ultra (128GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 114 | 122 | +7% | llama.cpp #4167 |
| M1 Ultra (128GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 1,180 | 1,138 | -4% | llama.cpp #4167 |
| M2 Ultra (192GB) | Llama-2-7b-hf FP16 | llama.cpp | Decode speed, 128 tokens | 49.5 | 47.7 | -4% | llama.cpp #4167 |
| M2 Ultra (192GB) | Llama-2-7b-hf FP16 | llama.cpp | Prompt processing, 512 tokens | 1,628 | 1,488 | -9% | llama.cpp #4167 |
| M2 Ultra (192GB) | Llama-2-7b-hf Q8_0 | llama.cpp | Decode speed, 128 tokens | 82.8 | 79.3 | -4% | llama.cpp #4167 |
| M2 Ultra (192GB) | Llama-2-7b-hf Q8_0 | llama.cpp | Prompt processing, 512 tokens | 1,487 | 1,488 | +0% | llama.cpp #4167 |
| M2 Ultra (192GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 125 | 122 | -3% | llama.cpp #4167 |
| M2 Ultra (192GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 1,489 | 1,488 | 0% | llama.cpp #4167 |
| M5 (16GB) | Llama-2-7b-hf Q8_0 | llama.cpp | Decode speed, 128 tokens | 18.4 | 18.8 | +2% | llama.cpp #4167 |
| M5 (16GB) | Llama-2-7b-hf Q8_0 | llama.cpp | Prompt processing, 512 tokens | 715 | 819 | +15% | llama.cpp #4167 |
| M5 (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Decode speed, 128 tokens | 31.9 | 33.3 | +4% | llama.cpp #4167 |
| M5 (16GB) | Llama-2-7b-hf Q4_0 | llama.cpp | Prompt processing, 512 tokens | 723 | 819 | +13% | llama.cpp #4167 |
| H100 SXM (80GB) | Llama-3.1-8B-Instruct FP8 | TensorRT-LLM | Decode speed, 1,500 tokens | 221 | 208 | -6% | NVIDIA NIM |
| H100 SXM (80GB) | Llama-3.1-8B-Instruct FP8 | TensorRT-LLM | Time to first token, 1,000 tokens | 19.0 | 19.0 | 0% | NVIDIA NIM |
| H100 SXM (80GB) | Llama-3.1-8B-Instruct FP16 | TensorRT-LLM | Decode speed, 1,500 tokens | 153 | 145 | -6% | NVIDIA NIM |
| H100 SXM (80GB) | Llama-3.1-8B-Instruct FP16 | TensorRT-LLM | Time to first token, 1,000 tokens | 27.4 | 27.0 | -1% | NVIDIA NIM |
| H200 SXM (141GB) | Llama-3.1-8B-Instruct FP8 | TensorRT-LLM | Decode speed, 1,500 tokens | 236 | 252 | +7% | NVIDIA NIM |
| H200 SXM (141GB) | Llama-3.1-8B-Instruct FP8 | TensorRT-LLM | Time to first token, 1,000 tokens | 19.8 | 19.0 | -4% | NVIDIA NIM |
| L40S (48GB) | Llama-3.1-8B-Instruct FP8 | TensorRT-LLM | Decode speed, 1,500 tokens | 71.6 | 78.0 | +9% | NVIDIA NIM |
| L40S (48GB) | Llama-3.1-8B-Instruct FP8 | TensorRT-LLM | Time to first token, 1,000 tokens | 44.6 | 44.0 | -1% | NVIDIA NIM |
| H200 SXM (141GB) | Llama-3.3-70B-Instruct FP8 | vLLM | Decode speed, 1,500 tokens, 4 at once | 46.5 | 40.2 | -14% | InferenceX |
| B200 (180GB) | Llama-3.3-70B-Instruct FP8 | vLLM | Decode speed, 1,500 tokens, 4 at once | 61.2 | 59.6 | -3% | InferenceX |
| Instinct MI300X (192GB) | Llama-3.3-70B-Instruct FP8 | vLLM | Decode speed, 1,500 tokens, 4 at once | 38.4 | 40.7 | +6% | InferenceX |
| Instinct MI325X (256GB) | Llama-3.3-70B-Instruct FP8 | vLLM | Decode speed, 1,500 tokens, 4 at once | 48.0 | 45.9 | -4% | InferenceX |
| Instinct MI355X (288GB) | Llama-3.3-70B-Instruct FP8 | vLLM | Decode speed, 1,500 tokens, 4 at once | 61.6 | 60.6 | -2% | InferenceX |
| H200 SXM (141GB) | Llama-3.3-70B-Instruct FP8 | TensorRT-LLM | Decode speed, 1,500 tokens, 4 at once | 49.7 | 47.8 | -4% | InferenceX |
| B200 (180GB) | Llama-3.3-70B-Instruct FP8 | TensorRT-LLM | Decode speed, 1,500 tokens, 4 at once | 68.5 | 69.8 | +2% | InferenceX |
| 2× RTX PRO 6000 Blackwell (96GB) | Qwen3.8-Flash-Next NVFP4 | vLLM | Decode speed, 1,750 tokens, 1 at once, MTP 3 tokens (2.54 per step) | 170 | 178 | +5% | Contributed run |
| 2× RTX PRO 6000 Blackwell (96GB) | Qwen3.8-Flash-Next NVFP4 | vLLM | Decode speed, 1,750 tokens, 12 at once, MTP 3 tokens (2.28 per step) | 56.8 | 61.0 | +7% | Contributed run |
Known gaps: llama.cpp prompt processing on datacenter GPUs varies more than one constant per class can follow (the H100 is predicted about 2× too fast, the L40 about 2.4× too slow), very large MoE models are on the optimistic side, and speeds for SGLang and Transformers are not checked against measurements yet.
Measurements from more hardware make the fit better. The benchmark script measures a running vLLM server or a GGUF file with llama-bench and writes a report to paste into a benchmark issue.
Fine-tuning
Memory
Full fine-tuning keeps the weights at the training precision (2 bytes for BF16, 4 for FP32, 1 for FP8), gradients of at least 2 bytes, an FP32 master copy (4 bytes) in mixed precision, and Adam's two moments (8 bytes, 2 with an 8-bit optimizer, 4 when the trainer stays in pure BF16). ZeRO stage 1 splits the optimizer states across GPUs, stage 2 also the gradients, stage 3 also the weights.
LoRA freezes the model in BF16 (QLoRA stores it in 4-bit NF4 with double quantization, 0.516 bytes per parameter, and keeps embeddings in 16-bit) and trains rank-r adapters on the attention (q, k, v, o) and MLP (gate, up, down) projections of every layer:
with q = nhdh and kv = nkvdh. Adapters take 2 bytes per parameter, their gradients 2, and their optimizer states 12 (4 for the FP32 copy and 8 for Adam, or 2 with an 8-bit optimizer).
Activations kept for the backward pass follow Korthikanti et al.: 34 × s × m × h bytes per layer for micro-batch m, plus 5 × nh × s² × m without flash attention. Gradient checkpointing keeps only each layer's input (2smh bytes) and recomputes one layer at a time; Unsloth also offloads those checkpoints, keeping about 30% on the GPU. Logits take 6 bytes per vocabulary entry per token, 0.5 with chunked loss (Unsloth, torchtune). The trainer gets 95% of GPU memory plus 1 GB of overhead.
Speed
κ is 6 FLOPs per parameter per token for full fine-tuning (forward 2, backward 4) and 4 for LoRA, which skips weight gradients, plus 2 when checkpointing recomputes the forward pass. φ is 1.4 for FP8 training on FP8 GPUs and q is 0.75 for QLoRA's dequantization. Training time is samples × epochs × sequence length divided by tokens per second.
| Trainer | Model FLOPs utilization (MFU) |
|---|---|
| Unsloth | 50% |
| torchtune | 42% |
| Transformers Trainer | 35% |
| Other | 35% |
Embedding and reranking
Encoders read each input once and keep no KV cache. Memory is the weights, activations of the batch (batch × s × (4h + 2dff) × 2 bytes) and 0.75 GB of overhead, out of 92% of GPU memory. A pass over n tokens takes:
with an MFU of 25% under 200M parameters, 40% under 2B and 50% above, and 85% scaling efficiency across GPUs.
Several models
The Advanced view places several models on a pool of machines with a greedy plan that is simple to follow rather than optimal. Pinned models are placed first, then the largest. Each model takes the fewest GPUs that fit and meet its targets (minimum speed per user, maximum time to first token), adding tensor parallelism or copies when one GPU group is too slow; a model spans identical machines with pipeline parallelism only when no single machine works. Automatic precision starts every model at the highest quality and steps all of them down together while that places more models or meets more targets, then lets each step back up if nothing gets worse. Idle GPUs end up as tensor parallelism or extra copies for the model that gains the most speed per user. Every placement is scored with the same engine.
Find hardware runs the current model on every GPU of the catalog at full, 8-bit and 4-bit precision; Find models runs every catalog model on your hardware.
Cost and energy
Load is 75% for inference, 90% for training and 60% for embedding. Energy per day is power × 24 h; emissions are that energy times the grid's carbon intensity (380 g CO₂ per kWh unless you change it); electricity costs $0.15 per kWh unless you change it. Cloud rental is a rough on-demand price per GPU-hour times the GPUs, over 720 hours a month.
Launch commands
The commands under Run it are built from the same setup: tensor and pipeline parallelism, context length, users, precision, KV cache format, speculative decoding, offloading and, for several copies, one process per copy with its own GPUs and port. They cover vLLM, SGLang, TensorRT-LLM, llama.cpp, Ollama, Transformers and Text Embeddings Inference, and Unsloth, TRL and torchtune for fine-tuning. Flags follow each project's documentation; check them against the version you install.
Sources
Data
- Models: the Hugging Face Hub API, each model's config.json and parameter count, rebuilt weekly by build-catalog.ts.
- GPUs: vendor spec sheets for memory, bandwidth, tensor throughput and power, with rough rental prices, in gpus.py.
- Speed measurements: llama.cpp scoreboards for CUDA, ROCm and Apple Silicon; NVIDIA NIM benchmarks; SemiAnalysis InferenceX. All rows are in benchmarks.json with their links.
- The quantization guide's perplexity figures are indicative; the cost of a format varies by model.
Methods
- Korthikanti et al., Reducing Activation Recomputation in Large Transformer Models, 2022. Activation memory.
- Rajbhandari et al., ZeRO: Memory Optimizations Toward Training Trillion Parameter Models, 2020.
- Hu et al., LoRA: Low-Rank Adaptation of Large Language Models, 2021. Dettmers et al., QLoRA: Efficient Finetuning of Quantized LLMs, 2023.
- Dao et al., FlashAttention, 2022. Kwon et al., Efficient Memory Management for LLM Serving with PagedAttention, 2023.
- DeepSeek-AI, DeepSeek-V2 (Multi-head Latent Attention), 2024, and DeepSeek-V3 (multi-token prediction), 2024.
- Leviathan, Kalman and Matias, Fast Inference from Transformers via Speculative Decoding, 2023. Li et al., EAGLE-3, 2025. Chen, Liang and Liu, DFlash: Block Diffusion for Flash Speculative Decoding, 2026.
- Patarasuk and Yuan, Bandwidth Optimal All-reduce Algorithms for Clusters of Workstations, 2009. Ring all-reduce traffic.
Related work on predicting LLM speed
- Patwari, Sirasao and Das, Forecasting LLM Inference Performance via Hardware-Agnostic Analytical Modeling (LIFE), 2025.
- WattGPU: Predicting Inference Power and Latency on Unseen GPUs and LLMs, 2026.
- Bambhaniya et al., Demystifying Platform Requirements for Diverse LLM Inference Use Cases (GenZ), 2024.
- Agrawal et al., Vidur: A Large-Scale Simulation Framework for LLM Inference, 2024.
Cite
If the calculator helps your work, please cite it:
Marius Brouty. VRAM Calculator: memory and speed estimates for LLM inference and fine-tuning. 2026. github.com/Marius-brt/VRAM-Calculator
@software{brouty_vram_calculator_2026,
author = {Brouty, Marius},
title = {VRAM Calculator: memory and speed estimates for LLM inference and fine-tuning},
year = {2026},
url = {https://github.com/Marius-brt/VRAM-Calculator}
}