cd /news/machine-learning/the-p100-has-been-doing-silently-noi… · home topics machine-learning article
[ARTICLE · art-56523] src=gist.github.com ↗ pub= topic=machine-learning verified=true sentiment=↑ positive

The P100 has been doing silently noisy math in llama.cpp for years. Three lines fix it for free.

A developer discovered that the Tesla P100 GPU has been performing inaccurate floating-point arithmetic in llama.cpp for years due to a missing architecture check. A three-line patch that excludes the P100 from fast fp16 paths reduces median Kullback-Leibler divergence by 2300× and increases top-token agreement from 96.53% to 99.89%, with no performance cost. The fix is now available in community pull requests and an upstream issue has been filed.

read4 min views1 publishedJul 12, 2026

The P100 has been doing silently noisy math in llama.cpp for years. Three lines fix it for free.

llama.cpp's CUDA backend has a FAST_FP16_AVAILABLE

flag: "this GPU is fast at fp16, so do quality-sensitive math in fp16." The GTX 10-series (sm_61) was exempted from it long ago. The Tesla P100 (sm_60) never was — because GP100 is the one Pascal chip with fast fp16 hardware. Hardware can, therefore software did. Nobody measured what it cost.

Measured against an fp32-arithmetic truth base (Qwen3.6-27B Q6_K, wikitext-2, 2048 ctx, 32 chunks, KLD over full logit distributions):

median KLD vs truth top-token agreement
stock llama.cpp on P100 0.002298 96.53%
3-line patch 0.000001
99.89%

That's ~2300× tighter, and roughly 1 in 29 next-token predictions were changing outright. The speed cost, benchmarked at pp8192/tg32 @ depth 8192 across three model classes (27B hybrid, 4B dense, 36B MoE): zero. Prefill inside noise on all three; decode +1.4% faster patched.

The patch is merged in llama-cpp-turboquant PR #212 and open in buun-llama-cpp PR #80. GGML upstream issue: ggml-org/llama.cpp#25593.

ggml/src/ggml-cuda/common.cuh

has three gates that all say the same thing:

#if defined(FP16_AVAILABLE) && __CUDA_ARCH__ != 610          // device macro
ggml_cuda_highest_compiled_arch(cc) != 610                    // fast_fp16_available()
cc >= GGML_CUDA_CC_PASCAL && cc != 610                        // fast_fp16_hardware_available()

sm_61 (GTX 1070/1080, P40) is carved out of all three — someone measured or knew that chip's fp16 story and made the right call. sm_60 (P100) sailed through all three gates because GP100 has genuine 2:1 fp16 hardware (18.7 TF). The fix extends the existing sm_61 idiom: && __CUDA_ARCH__ != 600

/ && cc != 600

. Three lines. That's the whole patch.

What those gates control on sm_60 (verified in dispatch source, not headers):

Flash-attention tile and vec kernels— all of attention math ran in half2 vector arithmetic. (Yes, llama.cpp has real working FA on Pascal — a fact the Python world, where FA2 requires sm_80, mostly doesn't know.)cuBLAS compute type— and this one's subtle: on sm_60, MMQ (the int8 quantized matmul path) ishard-disabled(should_use_mmq

returns false below the DP4A gate — GP100 missed the DP4A instruction by one minor arch version). So ALL quantized-weight prefill runs dequantize + cuBLAS GEMM, and this flag chose fp16 GEMM. Your entire weight path, in half precision, silently.mmvf— f16-weight matrix-vector arithmetic type.

Not by reading code — by measuring GPUs against each other. While validating a KV-cache codec (buun's TCQ/VBR work) across a P100 rig and a 3090, the same model, same weights, same test corpus kept producing systematically different KLD floors. Chasing that difference through a controlled decomposition panel (KV storage precision × attention arithmetic × weight-path arithmetic, each isolated) pointed at platform arithmetic, not the codec. The codec was innocent. The platform wasn't.

Key methodology point for anyone reproducing this class of bug: within-build comparisons cannot see it. If your truth base and your test run share the same fp16 arithmetic, the error is common-mode and cancels. Every rung of a KV-quant ladder measured on stock sm_60 looks clean relative to its own f16 baseline while the whole ladder sits ~0.005 median KLD away from the fp32 answer (with a 95.0% same-top floor — the weight-path error is ~2× the attention-path error). You must generate the reference logits with fp32 arithmetic to see it.

sm_60: measured, fixed. sm_61: was already exempt (nothing changes).sm_62 (Jetson TX2): same gate, same silicon family, unmeasured — deliberately NOT patched. Measure before you carve.Everything Volta+: unaffected by this patch. Independently verified by the turboquant maintainer pre-merge: these three gates are the only 600-vs-610 distinction in the CUDA tree, and a Blackwell build produced bit-identical PPL. (Whetherotherarches have their own distance-to-fp32-truth is a separate, open research question. Different flag, different kernels, different measurement. Don't extrapolate this bug to your 3090.)

P100s are flooding the used market at ~$80 shipped while the DRAM crisis prices everything else into orbit. That's 16GB of HBM2 at 732 GB/s per card. The market had it half-right: sm_61 P40s (clean math all along) soared to ~$300 while the P100 floundered — the price gap was partly pricing in a software bug. Post-patch, the P100 does fp32-clean inference at fp32 speed that was always there; the "fast" fp16 path it loses was buying nothing (real prefill is bound by cuBLAS GEMM and memory bandwidth, not the fp16 vector path).

  • Build stock llama.cpp, -DCMAKE_CUDA_ARCHITECTURES=60

. - Generate truth base: llama-perplexity --kl-divergence-base out.kld

with fp32 KV, FA off,on a patched build(fp32 arithmetic) — this is the step everyone skips. - Score stock vs patched runs against that base with --kl-divergence

, 2048 ctx, 32 chunks. - Speed: llama-bench

pp8192/tg32 @ d8192, patched vs unpatched, same host, nothing else on the GPUs.

Full panel design, predictions-logged-before-runs, and receipts: [https://github.com/apollo-mg/Project-Apollo/blob/1a41c11439e6661c84c83bec333ccdf964663da6/data/Apollo%20Docs/Pascal_FAST_FP16_Carveout_Results.md] [https://github.com/apollo-mg/Project-Apollo/tree/main/data/carveout_panel].

  • buun (TCQ/VBR codec) — the cross-GPU codec validation that surfaced the discrepancy, and the first fork PR review.
  • TheTom (llama-cpp-turboquant) — fast merge with independent cross-arch verification.
  • Found and isolated by running Fable 5 through my custom P/ReAct/R agent loop. It wrote the scripts, the hardware provided the receipts.
── more in #machine-learning 4 stories · sorted by recency
── more on @llama.cpp 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/the-p100-has-been-do…] indexed:0 read:4min 2026-07-12 ·