量化:FP8 与混合精度推理

量化:FP8 与混合精度推理

Charles Lv7

在量化讨论里,INT8INT4 很吸引眼球,但在很多工业服务栈中,真正迅速落地的是 FP8 和各种混合精度路径。
原因很简单:它们在硬件支持、数值稳定和 kernel 实现之间往往处在一个更实际的平衡点。尤其是大模型服务、训练后部署和多模态系统中,FP8 往往不是最激进的选择,却可能是最先产生稳定价值的选择。

这页重点回答四个问题:为什么 FP8 在很多系统里比 INT4 更容易先落地,为什么真实部署几乎从来不是“全模型统一一种精度”,FP8 的收益究竟来自显存、吞吐还是系统兼容性,以及在推理服务系统里哪些层值得保高精度。

初学者先抓住

FP8 不是“越低越好”的竞赛,而是一个更容易在硬件、kernel 和数值稳定之间兑现收益的折中。真实系统往往是混合精度:敏感层保守,热路径降精度。

有趣例子:不同路段限速

高速公路可以开快,学校门口必须慢。混合精度也是这样:GEMM 热路径可以尝试 FP8,某些 norm、输出头、风险相关模块可能要保留更高精度。

1. FP8 在解决什么问题

BF16/FP16 相比,FP8 主要希望降低显存占用和带宽压力,利用新硬件上的专门张量核心,同时保留比纯整数格式更自然的动态范围表示。

因此 FP8 常被视为一种“较温和的低精度路径”。

如果把单个张量元素存储位数从 16 bit 降到 8 bit,理论上存储和带宽需求都能大幅下降。
但 FP8 的真正意义不只是“省一半空间”,还在于它保留浮点格式的指数和尾数结构,对动态范围更友好,也更容易和现有浮点训练、推理栈衔接。

2. 为什么 FP8 比 INT4 更容易先进入生产

2.1 浮点格式对动态范围更宽容

整数格式往往要求你非常谨慎地选 scale。
而 FP8 由于保留指数位,面对范围跨度很大的张量时更自然。

很多激活张量会表现出这样的特性:

maxxmedian(x).\max |x| \gg \mathrm{median}(|x|).

这意味着张量里同时存在大量中小值和少量极端值。
如果用低比特整数硬压,往往会在“小值被量化成 0”和“大值被截断”之间摇摆。

FP8 在这里更有缓冲空间。

2.2 硬件和编译链支持更成熟

很多现代加速卡和编译栈已经逐步把 FP8 作为一类原生优化目标。这意味着 kernel 更成熟,张量核心更容易利用,编译器更愿意做自动图优化,服务框架也更容易接入。

而非常激进的低比特整数方案,虽然理论压缩率更高,但往往受限于:

特殊 kernel 支持不足、模型结构不兼容,或某些操作必须回退高精度。

2.3 混搭成本更低

很多团队已有大规模 BF16/FP16 训练和推理栈。
FP8 进入系统时更像在原有浮点链上降一级,而不是彻底换世界观。

这会降低调试成本,让数值异常更容易定位,也让它和现有模块混用得更自然。

3. 先建立一个概念:混合精度不是妥协,而是资源分配

在线服务里最常见的并不是“全模型 FP8”,而是某些权重层走 FP8,激活保留 BF16,softmax、norm、输出头保留高精度,跨模态投影或动作头再单独保护。

本质上这是在做精度预算分配:把高精度留给最敏感的环节。

更准确地说,混合精度是在回答下面这个问题:

在给定误差预算下,哪些张量最值得保高精度?\text{在给定误差预算下,哪些张量最值得保高精度?}

这和资金预算分配很像:不是所有层都同样重要,也不是所有操作对数值误差都一样敏感。合理分配精度,往往比追求“全局最低 bit”更稳。

4. FP8 的数值直觉

若张量 xx 映射到 FP8,实际关注的是动态范围和舍入误差。
与整数不同,FP8 可以在指数位上保留更大的范围变化,因此对范围跨度大的场景通常更稳。
但它仍然可能在极小值累积、归一化、残差叠加、长序列激活和极端 outlier 上遇到问题。

4.1 误差粗略写法

若量化映射为 x^=QFP8(x)\hat{x} = Q_{\text{FP8}}(x),则误差可写成:

e=xx^.e = x - \hat{x}.

在矩阵乘法 y=Wxy = Wx 中,权重和激活误差共同传播:

y^=(W^)(x^)=(W+δW)(x+δx).\hat{y} = (\hat{W})(\hat{x}) = (W + \delta_W)(x + \delta_x).

展开可得

y^y=Wδx+δWx+δWδx.\hat{y} - y = W\delta_x + \delta_W x + \delta_W \delta_x.

这说明数值退化不是单点发生,而是权重误差和激活误差一起作用。

4.2 为什么某些操作常常要保高精度

例如 LayerNormSoftmax、输出 logits 和某些 attention score 计算,对小量差异、指数放大和归一化稳定性非常敏感。
因此真实系统里,哪怕大部分 matmul 都压到 FP8,上述环节也经常保留更高精度。

5. 一个直观例子:为什么多模态系统更偏爱稳妥的混合精度

设想一个文档 VLM 系统,要同时处理 OCR 小字、布局坐标、图像 patch 和长文本上下文。

这类系统往往比纯文本 LLM 更容易受到数值精度变化影响。
原因在于不同模态张量的尺度差异更大,视觉投影层和文本层的数值分布不同,局部视觉细节对小数值误差也更敏感。

如果直接上激进的低比特整数方案,可能会出现:

OCR 细节丢失、表格边界理解退化或 grounding 精度下降。

这时 FP8 或 FP8 + BF16 混合精度就成为更现实的折中。

6. 服务时应如何看 FP8 价值

真正要看的不是“文件小了多少”,而是 TTFTTPOT 是否下降,显存释放后并发是否增加,长上下文下是否仍稳,多模态或长尾任务是否有不可接受退化,以及工程链是否更稳定。

很多时候,FP8 最大收益是让系统更容易塞进目标硬件,而不一定是理论吞吐数字最亮眼。

6.1 一个更实用的判断式

可以把上线价值粗略看成

ValueFP8=Δcapacity+ΔthroughputΔquality riskΔengineering complexity.\text{Value}_{\text{FP8}} = \Delta \text{capacity} + \Delta \text{throughput} - \Delta \text{quality risk} - \Delta \text{engineering complexity}.

这个式子提醒我们,性能提升要看端到端,风险和复杂度也必须算进去。

7. 哪些层适合优先尝试 FP8

虽然不同模型差异很大,但经验上更适合优先尝试 FP8 的位置通常是大型线性层权重、attention / MLP 的主要 matmul 和部分激活张量。更常需要保高精度的部分,则是 embedding / 输出头、norm 相关计算、softmax / logit,以及某些视觉投影或多模态融合层。

8. 三种典型部署场景

场景 A:70B 级文本模型服务

需求是把模型装进有限 GPU,让延迟可控,同时不希望质量掉太多。

这时 FP8 常常是一个好起点,因为:

它比 BF16 更省资源,比 INT4 风险更低,也更容易和成熟服务栈兼容。

场景 B:企业文档 VLM

需求是文本和图像都要保住细节,OCR 错误容忍度低,而且需要稳定上线。

这里更常见的路线是主干大部分 matmul 尝试 FP8,OCR 或关键结构层保 BF16,输出侧和规则判定部分保高精度。

场景 C:持续演化中的线上系统

如果团队仍在频繁更换模型版本、prompt 模板和工具链,那么采用一种过于激进的量化方案会显著加大回归成本。
FP8 的优势在于过渡平滑、异常更容易定位,也便于逐步扩展到更复杂的混合精度设计。

9. FP8 也有明确短板

9.1 它不是最极致的压缩路线

若目标是单卡塞超大模型、极限压缩或边缘设备部署,FP8 往往不如 INT4/W4A8 这类方案激进。

9.2 不是所有收益都会自动兑现

如果 kernel、框架或算子路径不成熟,理论上的 FP8 优势可能无法变成端到端收益。典型情况是某些算子回退高精度、频繁数据格式转换,或跨设备通信仍是主要瓶颈。

9.3 层选择不当仍会伤质量

“FP8 比 INT4 稳”不代表“随便压都没事”。
尤其在长上下文、复杂推理、文档细粒度理解和 agent 多工具任务中,局部敏感层被压坏后,问题依然明显。

10. 一份实践化落地顺序

若你准备把 FP8 引入推理服务系统,可按下面顺序推进:

阶段 重点
Profile 先确认瓶颈确实受带宽和显存影响
局部试点 从权重侧或主干 matmul 开始,不一次性压全部
保护敏感模块 norm、softmax、输出头等关键路径保留 BF16 或更高精度
回归验证 长上下文、多模态和长尾样本单独建桶
收益统计 同时看 TTFTTPOT、显存、并发和回退频率
继续降精度 只有收益真实可见后,再考虑更低比特

11. 小结

FP8 与混合精度推理的价值,在于它提供了一条更稳的压缩与加速路径。
对很多真实系统来说,它不是“最极致”的方案,却是最容易从实验室走向生产的方案。

更准确地说,它的核心价值不只是“8 bit”,而是保留浮点动态范围、便于与现有栈混合,并把低精度部署从一次性赌博变成可分阶段推进的工程设计。

快速代码示例

1
2
3
4
5
6
7
import transformer_engine.pytorch as te

def forward_step(model, x):
with te.fp8_autocast(enabled=True):
h = model.backbone(x) # 主干矩阵计算走 FP8
logits = model.lm_head(h.float()) # 输出头保留更高精度
return logits

这段代码演示了一个常见混合精度策略:主干高算量模块用 FP8 提升吞吐,敏感输出头保留更高精度以稳住质量。实际部署时还会配合分桶回归,确认长上下文和长尾任务不退化。

工程收束

FP8 的核心不是“比 BF16 更省”,而是精度管理、scale 策略、kernel 路径、cache 成本和回退策略是否一起成立。上线前先确定服务目标和硬件边界,再验证 scale 管理、kernel 命中率、TTFTTPOT、编译启动成本、cache 占用和回退频率;长上下文、多模态、工具调用、动作头等高风险路径要单独建桶,必要时保留高精度路径。

  • Title: 量化:FP8 与混合精度推理
  • Author: Charles
  • Created at : 2026-01-10 09:00:00
  • Updated at : 2026-01-10 09:00:00
  • Link: https://charles2530.github.io/2026/01/10/ai-files-quantization-fp8-and-mixed-precision-serving/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments