The FP8 Trap
Four different changes are called "turning on FP8." They return 1.15×, 1.45×, and 1.84× — and on an A100, exactly 1.00×.
Published: 2026-09-18 | jslet Research | 17 min read | Classification: Unrestricted
The Spec-Sheet Number Is a Peak, Not a Result
An H100 SXM5 does 989 TFLOPS of dense FP16 and 1,978 TFLOPS of dense FP8. That ratio — exactly 2×, by design, on the same silicon — is where every "FP8 doubles throughput" claim comes from. It is also close to irrelevant to your inference bill, for a reason that shows up the moment you look at what a decode step actually does.
Autoregressive decoding produces one token per step, and each step has to read the model's weights out of HBM before it can multiply anything. For Llama-3-8B at FP16 that is 16 GB of weights, and an H100 with 3.35 TB/s of memory bandwidth needs roughly 4.8 ms to stream them — about 210 tokens per second per sequence, before any overhead. The tensor cores sit almost idle during this, because a matrix-vector product at batch 1 has one column. You cannot speed it up by adding arithmetic throughput; you can only speed it up by moving fewer bytes.
That is the entire mechanism by which FP8 helps decode. One parameter in FP8 occupies one byte instead of two. The same model now needs 8 GB of weight traffic per step instead of 16 GB, so the ceiling on decode speed doubles. The ceiling — not the result. Everything else in this briefing is about the distance between that ceiling and what lands on the invoice, and that distance is set by choices that have nothing to do with the tensor-core ratio.
Prefill behaves differently. The first pass over a prompt is one large matrix-matrix multiply, which is compute-bound and does benefit from FP8's doubled arithmetic rate. So a prompt-heavy workload and a generation-heavy workload get different value from the same flag, and time-to-first-token improves on a different curve than inter-token latency. Model them separately: the inference latency calculator reports both.
Four Switches Called "FP8"
"We turned on FP8" is an ambiguous sentence in 2026, because at least four distinct changes get described that way. They touch different tensors, they are enabled by different flags, and the returns are not close to each other.
| The change | What is actually quantised | What it returns |
|---|---|---|
| W8A8 weights and activations | Model weights and the activations flowing between layers. Requires calibration or dynamic scaling, and is the change that halves weight bytes in HBM. | Roughly half the model memory, and the largest throughput gain of the four — vendor material quotes up to 1.6×, measured figures below run 1.45× to 1.84× depending on model size. |
| KV cache only | The key and value tensors stored per token per layer. Weights stay in BF16. | Roughly 14.8% off median inter-token latency and 14.9% more output throughput on the measured configuration below. Not 2×, and not 1.6×. |
| FP8 attention | The attention computation itself, which usually arrives bundled with FP8 KV cache rather than as an independent flag. | Couples to the KV-cache setting. Where flash-attention kernels support an FP8 path it composes with the cache saving; where they do not, you get the cache saving alone. |
| FP8 accumulation | Not a switch you flip — a property of the silicon. Hopper accumulates in FP8; Ada accumulates in FP16. | Nothing by itself, but it changes the value of the three above, because a datapath that converts between formats every step spends part of the saving on the conversion. |
The vLLM documentation is unusually direct about the confusion this produces, and the numbers are worth quoting precisely. Full weight-and-activation quantisation reduces model memory by about 2× with up to 1.6× throughput. The KV-cache flag alone, on the same model, returns about 1.15×. Both are legitimately "FP8," and a team that reads the first number, enables the second switch, and then measures a 15% gain will spend the afternoon looking for a bug that does not exist. The two settings compose — turning on both is the configuration that approaches the headline figure.
What NVIDIA Measured: 1.45× and 1.81×
The most useful published numbers here are NVIDIA's own, because they were produced by the people who sell the hardware, on a stack they control, and they still come out well below 2×. TensorRT-LLM throughput for Llama 3 at batch size 32, normalised per GPU:
| Model | Format | GPUs | Tokens/sec | Speedup |
|---|---|---|---|---|
| Llama 3 8B | FP16 | 1 | 2,293 | — |
| Llama 3 8B | FP8 | 1 | 3,331 | 1.45× |
| Llama 3 8B | INT8 SmoothQuant | 1 | 3,204 | 1.40× |
| Llama 3 8B | INT4 AWQ | 1 | 2,476 | 1.08× |
| Llama 3 70B | FP16 | 4 | 256 | — |
| Llama 3 70B | FP8 | 2 | 464 | 1.81× |
| Llama 3 70B | INT8 SmoothQuant | 2 | 463 | 1.81× |
| Llama 3 70B | INT4 AWQ | 2 | 361 | 1.41× |
Two rows matter more than the speedup column. The 70B FP8 engine runs on two H100s where the FP16 baseline needs four. Every quantised variant of that model fits on one card, which is where the 2× resource saving actually comes from — a saving in GPU count rather than in milliseconds. And the same measurement at batch size 1 reverses the ordering of the formats entirely.
| Model | Format | Tokens/sec (batch 1) | Speedup |
|---|---|---|---|
| Llama 3 8B | FP16 | 135.8 | — |
| Llama 3 8B | FP8 | 170.8 | 1.26× |
| Llama 3 8B | INT4 AWQ | 211.5 | 1.56× |
| Llama 3 70B | FP16 | 17.8 | — |
| Llama 3 70B | FP8 | 32.6 | 1.84× |
| Llama 3 70B | INT4 AWQ | 47.1 | 2.66× |
Read the two tables together and the shape of the decision appears. FP8 gains more as the model gets bigger, because a bigger model spends more of each step on weight traffic. FP8 loses to INT4 as the batch gets smaller, because a smaller batch has less arithmetic to hide the memory traffic behind. Neither of those is a property of the format; both are properties of the workload.
Where INT4 Quietly Beats FP8
The row most people skim past is INT4 AWQ at 2.66× on Llama 3 70B at batch 1, against FP8's 1.84×. That is not a rounding artefact, and it is not a vendor preference. It follows from the bandwidth argument in the first section: at batch 1 there is no batching to amortise anything, so the step time is the time to read the weights, and four-bit weights are half the bytes of eight-bit weights. A 70B model needs 141 GB of weight traffic per token at BF16, 70 GB at FP8, and 35 GB at INT4. On a single H100 the last of those is simply faster, and no amount of tensor-core throughput changes it.
What FP8 sells instead is accuracy retention. Measured MMLU degradation across quantisation methods puts the formats in a clear order:
- FP8: 0.14 to 0.87 points. Frequently inside run-to-run noise on a single evaluation.
- INT4 AWQ: 0.85 to 2.11 points. Acceptable for chat and retrieval, visible on reasoning and arithmetic.
- INT8 SmoothQuant: 2.50 to 2.75 points. Counter-intuitively worse than INT4 AWQ on this metric, because the activation quantisation is where the damage happens.
So the honest framing of the choice is not "fastest versus slowest." It is: if the workload can absorb a point or two of accuracy — a support chatbot, a summariser, a classification pass — INT4 is the cheaper format and the faster one. If it cannot — code generation, multi-step reasoning, anything where a wrong token costs a retry — FP8 is the format that buys most of the memory saving while leaving the answers alone. INT8 SmoothQuant sits in an awkward middle: more accuracy loss than FP8 at the same one byte per parameter, which is why it has been losing ground since FP8 hardware arrived.
The 7,010-Token Break-Even
FP8 KV cache is not free at the margin. It adds a small constant cost per attention step — extra scale handling, and a conversion where the kernel has no native FP8 path — and that constant only becomes negligible once the cache is long enough that the halved memory traffic is the dominant term. For Llama-3.1-8B the two terms cross at 7,010 tokens of context.
Below that, FP8 KV cache is slower than leaving the cache in BF16. A deployment built on short prompts — a classification service, a routing layer, a JSON-extraction endpoint that sees 500-token inputs — is exactly the workload where "we enabled FP8" produces a regression and a confused engineer. On the same model at concurrency 1, the fitted inter-token-latency slope fell from 4.37×10⁻⁵ to 2.37×10⁻⁵ ms per token, which is 54% of the BF16 slope and close to the theoretical floor, while the intercept moved only from 6.44 ms to 6.58 ms. That intercept is the constant cost. At short contexts you are paying it without collecting the slope reduction.
Two structural cases never reach break-even at all:
- Models with head_dim = 256. These require two-level accumulation for FP8 attention, which raises time-to-first-token by roughly 1.6× at long context. Prefill in BF16 and quantise only the cache is the usual workaround, and it is worth validating accuracy separately because the two-level path is not bit-identical to the single-level one.
- Stacks with many small sliding-window layers. Each layer adds the fixed cost and contributes little cache to amortise it, so the overhead accumulates across layers without a corresponding traffic reduction.
Above the threshold the gain is dependable. The reference measurement — a single H100 with FlashAttention-3, Llama-3.1-8B, concurrency 8 — moved median inter-token latency from 15.18 ms to 12.93 ms, median time-to-first-token from 763.6 ms to 742.8 ms, and output throughput from 450.3 to 517.5 tokens per second. Two effects combine: each token decodes faster, and the 2× cache reduction lets the scheduler hold more concurrent requests in the same memory, so the card serves more sequences at once.
On A100, FP8 Is Free and Worth Nothing
This is the trap that costs the most engineering time, because it does not fail. Ampere's third-generation tensor cores accelerate FP16, BF16, TF32, INT8 and INT4. They do not accelerate FP8. Frameworks do not error out on this. They fall back to the nearest supported format with a conversion step around it, the job completes, the logs stay clean, and the throughput lands at approximately BF16 levels.
Two things are true simultaneously, and separating them is the whole point:
| Property | On Ampere (A100) | On Hopper (H100/H200) |
|---|---|---|
| Weight bytes in HBM | Halved — the tensors really are 8-bit | Halved |
| Does the job run? | Yes, with no error raised | Yes |
| Throughput versus BF16 | ≈ 1.00×, plus conversion overhead | Up to 1.81× measured |
So on Ampere, FP8 is a memory decision, not a performance decision. It is a perfectly good way to fit a model that would otherwise require a second card — the weights genuinely shrink — and a completely ineffective way to make that card faster. If your fleet is A100-based and your problem is tokens per second, the quantisation menu is INT8 or INT4, and INT8 on A100 delivers roughly a 50% throughput gain against FP8's zero. This is not a driver limitation waiting on a patch. The silicon either has execution units for a format or it does not, and no framework update adds them.
The same trap exists one level down. Running INT8 inference on a V100 drops to CUDA cores and lands far below what an A100 achieves on the identical workload. Whenever a format is chosen for a GPU generation, the first question is which tensor-core generation is doing the work — not what the format promises in the abstract.
Ada Has FP8. It Isn't Hopper's FP8.
Between "no FP8" and "full FP8" there is a third state that the specification sheets blur together. Ada Lovelace parts — the L40S, the L4, the RTX 4090 — do accelerate FP8, starting at compute capability 8.9 with CUDA 12.1 and cuBLASLt 12.1.3. What they do not have is Hopper's datapath.
| Generation | Compute capability | Native tensor-core formats | FP8 accumulate |
|---|---|---|---|
| Volta (V100) | 7.0 | FP16 | — |
| Ampere (A100) | 8.0 | FP16, BF16, TF32, INT8, INT4 | — (no FP8 units) |
| Ada (L40S, L4, RTX 4090) | 8.9 | Ampere's menu plus FP8 (E4M3, E5M2) | FP16 accumulate |
| Hopper (H100, H200) | 9.0 | Full FP8 datapath | FP8 accumulate |
| Blackwell (B200) | 10.0 | Hopper's plus MXFP8 and NVFP4 | FP8 accumulate, block scaling |
The distinction is not academic. FP8's dynamic range is narrow, and keeping values inside it depends on scaling — per-tensor at minimum, per-block for the more aggressive recipes. Hopper's Transformer Engine performs that scaling on dedicated units and tracks a rolling maximum to compute the next step's scale factor without a synchronisation point at every layer. On a part without that hardware the scaling still happens, just on general-purpose paths, and each conversion round-trips through FP16. The result is that the same nominal FP8 precision returns less on Ada than on Hopper, and the gap widens as the scaling recipe gets finer-grained.
There is a practical consequence for capacity planning. "Supports FP8" on a specification sheet tells you which formats the multiply units accept. It does not tell you whether the scaling machinery that makes FP8 usable is the one the hardware accelerates. For a blockwise recipe — microscaling, or anything per-group rather than per-tensor — that second question is the one that decides whether the format pays for itself, and it is the one that datasheets leave unanswered.
Utilisation Outranks Precision
All of the above is second-order. Here is the same AWS instance — p5.48xlarge, eight H100s — priced four ways, with the implied cost of a million output tokens under each. Rates are from June 2026 listings:
| Purchase model | Per GPU-hour | BF16 $ / 1M tokens | FP8 $ / 1M tokens |
|---|---|---|---|
| On-demand | $6.88 | $4.24 | $3.69 |
| Spot | $3.37 | $2.08 | $1.81 |
| 3-year reserved | $2.97 | $1.83 | $1.60 |
| 3-year reserved, 50% idle | $5.94 | $3.67 | $3.19 |
The last row is the one to stare at. A three-year commitment at half utilisation costs $3.19 per million FP8 tokens. On-demand FP8 costs $3.69. The cheapest contract in the table becomes the second-most-expensive line the moment the card sits idle half the day — and it is a difference of fourteen cents per million tokens, which is larger than the entire gap between BF16 and FP8 on-demand. Meanwhile switching spot to reserved is worth $0.21 per million, and switching on-demand to spot is worth $1.88.
That ordering is the whole lesson. Fix utilisation, then fix the purchase model, then quantise. Most teams do it backwards, because quantisation is the part with a flag attached and a benchmark to run, and renegotiating a commitment or deleting an idle replica is the part that requires a conversation. The arithmetic does not care which was more fun. A pipeline that runs at 50% duty cycle has already spent more money than any precision change will recover, and no amount of FP8 closes a utilisation gap.
The same logic applies to the model itself. A quantisation decision that drops GPU count from four to two is worth more than any per-token improvement, because it removes a whole card from the bill. The 70B FP8 engine above, serving on two H100s instead of four, is the largest single saving in these tables.
What a Million Tokens Actually Costs
Combining the pieces gives a working estimate for a real deployment. Take Llama 3 70B, batch 32, one on-demand H100-class GPU-hour at $6.88, and the measured throughputs above collapsed to a single card for comparability:
The FP16 row is where the money hides. It is not that 256 tokens per second is slow — it is that 256 tokens per second requires two cards, and the bill counts cards, not tokens. FP8 on 70B wins here by a factor of 3.6× against the FP16 baseline, and the reason is almost entirely the GPU count: 1.81× more throughput per GPU, on half as many GPUs. That is what a "2× speedup" turns into once it is expressed in money, and it is why the model-size dependence in the earlier table matters so much. The same flag on the 8B model returns 1.45× on one card, which is $4.90 per million instead of $7.10 — real, but nowhere near a factor of three.
Two caveats keep these numbers honest. First, they price output tokens only; prompt processing happens at different rates and is what time-to-first-token measures, so a prompt-heavy workload should be modelled through the latency calculator rather than multiplied out from a single throughput figure. Second, they assume the card is doing useful work every hour it is billed, which is exactly the assumption the previous section spent its length dismantling. Run the top row of that table at 50% duty cycle and the FP8 figure becomes $8.24 per million — still better than FP16, and worse than simply running the same workload on spot.
For the memory side of the same decision, the parameter-to-VRAM converters handle FP16 and INT4 directly. The KV cache is modelled separately in the context window inflation calculator — the right place to check whether a long-context service can hold the concurrency its throughput implies.
A Four-Question Decision Procedure
Run these in order. The first one that produces a "no" ends the analysis, because every later question assumes the earlier ones passed.
- Is the GPU generation native for FP8? Hopper (9.0), Blackwell (10.0), or Ada (8.9) — yes. Ampere (8.0) and older — stop here, and choose INT8 or INT4 instead. On A100 the throughput answer is no regardless of what the framework accepts without complaint.
- Is the model large enough to care? The measured gain runs from 1.45× at 8B to 1.81× at 70B at batch 32. If the model is small, the weight traffic is not the dominant term and FP8 will disappoint. If it is large enough to need a second GPU at BF16 and only one at FP8, the win is structural rather than incremental.
- What is the operating batch size? At batch 1, INT4 beats FP8 outright (2.66× against 1.84× on 70B) because decode is pure weight traffic. High-concurrency serving is where FP8's accuracy advantage becomes affordable; single-stream interactive use is where INT4's bandwidth advantage wins.
- Does the context length clear the break-even? For FP8 KV cache specifically, below roughly 7,000 tokens the overhead dominates and the change is a regression. Check head_dim as well — 256-dimensional heads need two-level accumulation that costs about 1.6× on time-to-first-token at long context.
And before any of the four, check the utilisation number. A GPU that is idle half the month costs more than the precision decision can save, in every configuration in the table above.
Frequently Asked Questions
Does FP8 really double LLM inference throughput?
Not on its own. The 2× figure is the ratio between FP8 and FP16 tensor-core peak on an H100 — 1,978 against 989 TFLOPS — and decode does not run at tensor-core peak, because every generated token requires reading the active weights once from HBM. FP8 helps decode by halving the bytes of weight traffic, which sets a 2× ceiling that no real deployment reaches. Measured results from NVIDIA's TensorRT-LLM benchmarks on Llama 3: 1.45× on the 8B model at batch 32, 1.81× on the 70B at batch 32, and 1.84× on the 70B at batch 1. The gain grows with model size because a larger model spends a larger share of each step moving weights rather than doing anything else.
Why does INT4 beat FP8 at batch size 1?
Because at batch 1 the step time is set almost entirely by how many bytes come off HBM to produce a single token, and INT4 weights are half the size of FP8 weights. In NVIDIA's measurements on Llama 3 70B at batch 1, INT4 AWQ reached 2.66× over FP16 while FP8 reached 1.84×. The trade is accuracy, and it is measurable: MMLU degradation runs 0.14 to 0.87 points for FP8, 0.85 to 2.11 points for INT4 AWQ, and 2.50 to 2.75 points for INT8 SmoothQuant. FP8's selling point is not that it is the fastest format. It is that it is the fastest format that barely changes your model's answers.
What is the break-even context length for FP8 KV cache?
About 7,010 tokens for Llama-3.1-8B. FP8 KV cache carries a small fixed overhead per attention step that only pays for itself once the cache is long enough for the halved memory traffic to dominate. Below roughly 7,000 tokens the overhead is the larger term and FP8 is slower than BF16. Two cases never amortise at all: models with head_dim of 256, which need two-level accumulation that raises time-to-first-token by about 1.6× at long context, and stacks with many small sliding-window layers, which spread the fixed cost across too little cache to recover it. Above the threshold the gain is real — on one H100 with FlashAttention-3 at concurrency 8, Llama-3.1-8B moved from 15.18 ms to 12.93 ms median inter-token latency for 14.9% more output throughput.
Can I use FP8 on an A100?
You can issue the instructions and they will run, but you will not get a throughput benefit. Ampere's third-generation tensor cores support FP16, BF16, TF32, INT8 and INT4, and not FP8. Frameworks do not fail in this situation — they fall back to a supported format with a conversion step, so an FP8 job on an A100 produces roughly BF16 throughput and raises no error. The memory saving is real, because the weights genuinely occupy half the bytes in HBM. So on Ampere, FP8 is a memory-footprint decision rather than a performance one: a good way to fit a model that would otherwise need a second card, and an ineffective way to make that card faster.
Is FP8 on an L40S the same as FP8 on an H100?
No. Both accelerate FP8 GEMMs, but they differ in the accumulate path and in the scaling hardware. Ada Lovelace parts such as the L40S and L4 run FP8 multiplies with FP16 accumulation. Hopper runs the whole datapath in FP8 — inputs, products and accumulator — and pairs it with the Transformer Engine, which performs per-tensor dynamic scaling on dedicated units to keep values inside FP8's narrow exponent range. Blockwise and microscaling recipes depend on that scaling hardware; where it is absent, the scaling runs on slower general paths and erodes the throughput the format was chosen for. A specification sheet saying the part supports FP8 does not tell you whether the scaling path that makes FP8 useful is the one the hardware accelerates.
Methodology & Disclosure
Tensor-core peak figures (FP16 989 TFLOPS, FP8 1,978 TFLOPS dense on H100 SXM5) are the manufacturer's published dense ratings. Throughput tables are NVIDIA's published TensorRT-LLM results for Llama 3 8B and 70B at batch sizes 32 and 1, and are normalised per GPU as published. Inter-token-latency, time-to-first-token and the 7,010-token break-even come from the FlashAttention-3 FP8 KV-cache validation study published on the vLLM blog in April 2026, measured on a single H100 at concurrency 1 and 8. MMLU degradation ranges are the ranges reported across the same quantisation methods. Instance rates are June 2026 on-demand, spot and three-year reserved listings for AWS p5.48xlarge (eight H100s), divided by eight for the per-GPU figures. Cost-per-million-token figures are computed from those rates and the throughputs above, assume continuous useful utilisation, and cover output tokens only. This site takes no sponsorship, no affiliate commission and no vendor payment of any kind; the vendors named here have no relationship with jslet and did not review this briefing.
References & Further Reading
- NVIDIA Developer Blog. "Post-Training Quantization of LLMs with NVIDIA NeMo and NVIDIA TensorRT Model Optimizer." Throughput tables for Llama 3 8B and 70B, batch sizes 32 and 1. developer.nvidia.com
- vLLM Blog (Kübler, Budhathoki, Kurtić et al.). "FP8 KV cache with FlashAttention-3: validation study." April 2026. Inter-token latency, time-to-first-token, break-even context and failure modes. blog.vllm.ai
- NVIDIA Transformer Engine. GPU compute-capability feature matrix: FP8 gating at SM 8.9 (Ada, CUDA 12.1 / cuBLASLt 12.1.3 minimum) and full FP8 at SM 9.0 (Hopper). github.com/NVIDIA/TransformerEngine
- NVIDIA. H100 Tensor Core GPU architecture whitepaper — FP8 E4M3/E5M2 formats, Transformer Engine, and the dense FP16/FP8 throughput ratings. nvidia.com
- Related: LLM Inference Latency Calculator · Self-Hosted LLM vs API Breakeven · Token Economics: Why Your LLM Bill Is 3× the Sticker Price · GPU Training Costs: The arXiv-to-Bill Gap
📜 Copyright & Attribution
Published 2026-09-18 by jslet Research · jslet.com
You may quote up to 200 words with a link to this page. For syndication, translation or full-text reuse, contact jslet. Figures are current as of September 2026 and are drawn from published vendor measurements; reproduce the methodology if you cite the numbers.
Run the numbers on your own model
The LLM inference latency calculator models throughput against memory bandwidth across 12 models and 10 GPUs, including FP8. If the question is whether self-hosting beats an API at your volume, the breakeven calculator takes the throughput number this briefing produces and turns it into a decision.