# 企业 AI 落地该选 FP8 还是 FP4？量化格式的成本、质量与硬件决策

> 一个 70B 客服系统的部署账：FP8 只动权重，KV cache 会把省下的显存吃回去；FP4 在 Blackwell 上吞吐更高，结构化输出的字段错误却能把 GPU 省下的钱赔回去。附 vLLM 参数、字段级验收和采购时要问的硬指标。

Canonical: https://zzszmyf.github.io/notes/%E4%BC%81%E4%B8%9Aai%E8%90%BD%E5%9C%B0%E9%80%89fp8%E8%BF%98%E6%98%AFfp4-%E9%87%8F%E5%8C%96%E6%A0%BC%E5%BC%8F%E7%9A%84%E6%88%90%E6%9C%AC%E8%B4%A8%E9%87%8F%E4%B8%8E%E7%A1%AC%E4%BB%B6%E5%86%B3%E7%AD%96/


70B 客服系统，8K 上下文，32 并发，原来 4 张 H100 跑 BF16：权重 140GB，KV cache 80GB，显存看着还有余量，GPU 利用率却常年在 30% 上下。问题就变成能不能砍到 2 张卡，FP8 够不够。下面这组数字是我拿来算账的模型，并非某家客户的原始数据；你换成自己的 tokens/s 和卡价，结论可能完全不同。

只把权重换成 FP8，权重从 140GB 降到 70GB，2 张 H100 账面装得下。按这组账，P95 会回到原点：KV 还按 FP16 算，70GB 权重加 80GB KV 已经 150GB；`--gpu-memory-utilization 0.9` 把 2×80GB 的可用显存压在 144GB，就算你把 `--max-num-seqs 32` 写死，启动日志里的最大并发也会掉到 32 以下，运行时靠 preemption 腾 KV，延迟自然回去。把 KV 也切到 FP8，KV 从 80GB 降到 40GB，2 张卡才真正稳住 32 并发。顺序很重要：先权重、再 KV、最后再碰 attention；每加一项单独跑验收，两项一起上，出问题后很难归因。

再看 FP4。B200 上一张卡就能装下 35GB 权重加 40GB KV，吞吐确实高；如果结构化输出的失败率从 0.2% 涨到 2.1%，账就变了。按 1,000 次采样算，21 次会把 `amount` 写成字符串 `"1,280.00"`，3 次丢 `currency`，支付网关会直接返回 400。模型没报错，业务失败。量化格式最后会同时改三样东西：卡数、P95、字段级失败率。前两个在容量规划里看得见，第三个要到支付网关返回 400 时才看得见。这两个失败率是我为算账设的，换成 `[待补：目标业务金标准集上 BF16/FP4 的字段级失败率]` 之后，下面的成本结论要重算。

## 显存和带宽，两个账本

70B 模型，BF16 每参数 2 字节，权重 140GB；FP8 是 70GB；FP4 是 35GB。很多人算到这里就停了。实际还要加 KV cache、prefill 的激活、CUDA Graph 和通信缓冲。工程上先按权重的 1.2–1.5 倍留余量，长上下文再单独算 KV。

以 Llama-3-70B 的 GQA 配置为例，80 层、8 个 KV 头、head_dim 128。每个 token 的 KV 是：

$$
2 \times 80 \times 8 \times 128 \times 2 \text{ bytes} \approx 0.31 \text{ MiB}
$$

8K 上下文一个序列 2.5GiB，32 并发就是 80GiB；同样 32 并发，32K 是 320GiB，128K 是 1.25TiB。FP8 权重省下的 70GB，在 32K 上下文下，一个序列的 KV 就是 10GiB；七个序列就把这 70GB 吃回去了。vLLM 用分页 KV cache 管理这些块，默认 block size 是 16；启动时会打印 `GPU blocks` 和对应请求长度下的最大并发。这两个数比 `nvidia-smi` 的显存占用有用得多。显存占用 95% 不代表你能跑 32 并发，可能只是碎片、CUDA Graph 和通信缓冲把余量吃掉了。KV 量化的细节在 [KV Cache 量化怎么做](/notes/llm量化精读笔记-08-kv-cache量化与kivi/)。

prefill 和 decode 的瓶颈不一样。prefill 吃的是 Tensor Core 的 FLOPS，FP8 在 Hopper/Ada 上有原生指令，矩阵乘吞吐能到 BF16 的约 2 倍；decode 吃的是 HBM 带宽，FP8 的价值是把每 token 要读的权重大小减半。这里要区分两种 FP8：只量化权重（W8A16）省的是 decode 的 HBM 读取；W8A8 把激活也压到 FP8，prefill 的矩阵乘才吃满 FP8 Tensor Core。前面第一步只换权重，下面成本账里的 FP8 指的是 W8A8 加 KV FP8。很多团队用一个总的 tokens/s 判断量化有没有用，结果 prefill 快了、decode 没变，P95 还是不动。

decode 的单请求上界是：

$$
\text{tokens/s} \lesssim \frac{\text{有效 HBM 带宽}}{\text{每 token 读取字节数}}
$$

70B、BF16、H100（3.35TB/s）：3.35TB/s ÷ 140GB ≈ 24 tokens/s。FP8 把读取量减半，同一张 H100 上的理论上限约 48 tokens/s。实际值会被 kernel 效率、batch、KV 读取和通信拉低。你如果在 `nvidia-smi` 里看到显存占用 95%、SM 利用率只有 20%，那基本就是 decode 在等 HBM；这时候先把权重和 KV 的数据量降下来，比换一张更快的卡更直接。

还有一个容易被忽略的收益：4 卡 TP 降到 2 卡 TP，decode 路径上的 all-reduce 组从 4 卡缩到 2 卡，每 token 的同步开销也跟着降。省卡省的是钱，少一轮通信省的是 TPOT，这两笔账经常被混在一起算。

## 硬件没有对应指令，格式就拿不到收益

Ampere 的 A100/A800 没有 FP8 Tensor Core 指令；Ada 的 L40S、4090 有 FP8；Hopper 的 H100/H200 有 FP8；Blackwell 的 B200/GB200 才有 FP4。国产卡不要按品牌推断，直接看具体型号的算子清单和引擎支持。A100 上谈 FP8，基本拿不到硬件收益：权重可以存成 FP8 省显存，但矩阵乘还要拆成 BF16 或走软件路径，省不下计算。把它写进新项目承诺，是给自己挖坑。FP4 需要和块缩放一起看。它用 E2M1 元素，配合块缩放才能用：NVFP4 每 16 个元素一组，MXFP4 每 32 个一组，缩放因子和工具链都不同。H100 上没有 FP4 Tensor Core，所谓 FP4 只能做权重存储，计算还得反量化；在 H100 上讨论 FP4 加速，拿不到计算收益。

私有化部署和在线服务的约束不一样。私有化买卡，扩容周期按季度算，选型要按三年容量规划；在线客服按 P95 和单位 token 成本算，FP8 加 KV FP8 更容易同时满足；边缘一体机看单机显存和功耗，W4A16/INT4 更常见。云端 FP4 的评测结论不能直接搬到边缘设备，kernel、内存带宽和功耗墙都不同。

## 把 70B 的账算一遍

假设 70B dense、8K 上下文、32 并发，三种方案都要满足同一 P95 SLA。按前面的显存账，BF16 需要 4×H100 80GB，FP8 用 W8A8 加 KV FP8 需要 2×H100，FP4 需要 1×B200 192GB。每百万 token 的成本，就是每小时卡钱除以每小时产出的 token 数。假设 H100 每小时 20 元、B200 每小时 50 元，三种方案都跑满，吞吐按 1,000、1,600、2,500 tokens/s 算。BF16 每小时 80 元，产 3.6M tokens，每百万 token 22.2 元；FP8 每小时 40 元，产 5.76M，6.9 元；FP4 每小时 50 元，产 9M，5.6 元。实际利用率不一样，按各自的小时产出折算，别直接套这三个数。

这组数字最敏感的是两处。按上面的吞吐假设，B200 单卡时价超过 H100 的约 3.1 倍（62.5 元/小时），FP4 每百万 token 就比 FP8 贵；B200 停在 50 元/小时，FP4 才领先。另一头是 FP8 的吞吐：如果它只有 BF16 的 1.2 倍，每百万 token 约 9.3 元，相对 BF16 的 22.2 元仍然便宜一半以上。真正让 FP8 失效的是卡数降不下来；吞吐少快一点只影响领先幅度。别拿厂商的峰值算，拿你线上的 batch、上下文和 P95 算；没有实测就先跑 200 条请求，拿到 tokens/s 和 P95 再算。如果卡是买的，把小时单价换成三年折旧加电费运维，算法不变。

还有一笔账不在 GPU 里。按 2.1% 的失败率，100 万次月请求就是 2.1 万次字段错误；每次人工兜底 8 块钱，一个月 16.8 万。假设 FP4 一个月省 3 万 GPU 费，这笔钱不够填：16.8 万是 3 万的 5.6 倍。这个算术不复杂，难的是你有没有把字段级失败率测出来。

## 质量验收要落到字段级

这些失败集中在退款金额、币种和带小数点的字段上，通用 benchmark 测不出来，得拿业务金标准集按字段做配对比较。上线前至少跑 500 条真实业务样本，覆盖高频、长尾、边界和对抗输入；同一 prompt 做 BF16 和量化的配对比较，看变差率，不只看平均值。

客服场景可以先用这组门槛：JSON schema 合法率 ≥99.5%，业务准确率相对基线下降 ≤1 个百分点，P95 TTFT ≤800ms，TPOT ≤50ms。按 1%→10%→50% 灰度，连续 24 小时任一指标不达标就回滚。回滚要保留 BF16/FP16 副本，按请求或按租户切回。vLLM 里可以先用 `--quantization fp8` 跑权重 FP8，再单独开 `--kv-cache-dtype fp8` 跑 KV 量化；版本以你锁定的为准。KV cache 量化先上 FP8，别一上来就 INT4；INT4 的误差和 kernel 支持都更激进，长上下文 RAG 最先出事。完整的评测方法在 [量化后精度掉了怎么定位](/notes/llm量化精读笔记-10-质量评估方法论/)。

合同审查、代码生成、风控这些任务对字段和数值更敏感，阈值要按业务单独定，不能直接套客服的 99.5%。长上下文业务再加一组远端证据召回测试；attention 默认留在 FP16/BF16，FP8 attention 只在有专用 kernel、长序列占比高、评测通过时才考虑。

对外采购时，把这套验收变成可验证的条款。先问这个格式在哪个具体 SKU、哪个引擎版本上有原生 kernel，给 batch、上下文、并发和端到端吞吐；再问 KV cache 在 32K/128K 下怎么放，显存账怎么算；最后问精度或性能不达标时，回退路径是什么，回退后的延迟和成本是多少。别问“支持不支持 FP8”，那个问题没有意义；要问的是在你的 batch 和上下文下，端到端 tokens/s 是多少。NVFP4 和 MXFP4 也在这里问清楚：前者绑定 NVIDIA 工具链，后者是 OCP 标准，换卡换云的成本要提前算。部署侧的 kernel 坑，可以顺着 [量化模型怎么部署到 vLLM](/notes/llm量化精读笔记-11-系统协同与部署/) 继续看。

如果只给一个默认建议：新采购的 Hopper/Ada 走 W8A8 FP8 加 KV FP8；Ampere 存量按上面的硬件代际判断；FP4 的取舍交给实测。我不建议为了省一张卡去上 FP4，除非你已经有一套字段级评测和按请求回滚的机制；按上面的假设，一个月 16.8 万的兜底成本是 3 万 GPU 差价的 5.6 倍。最终选型落到同一批流量、同一套 SLA、同一组金标准的对照测试，分别跑 BF16、FP8、FP4，记录卡数、吞吐、P95 和字段级失败率；如果 FP4 的字段错误率压不下来，省下的卡就只是把成本挪到了人工兜底。

参考：NVIDIA 的 [FP8 白皮书](https://arxiv.org/abs/2209.05433)；OCP 的 [Microscaling Formats 规范](https://www.opencompute.org/documents/ocp-microscaling-formats-mx-v1-0-spec-final-pdf)；[QServe 论文](https://arxiv.org/abs/2405.04532)；[vLLM 的量化文档](https://docs.vllm.ai/en/latest/features/quantization/)。格式细节和逐章推导在 [LLM 量化精读笔记](/notes/llm量化精读笔记-00-总览与学习地图/)。

