2、量化基础:从FP32到INT8—— 什么是量化?量化如何同时影响速度和精度?

大家好,我是你们的老朋友。今天咱们来聊聊大模型部署里最绕不开的一个话题——量化。

说实话,我刚入行那会儿,听到「量化」两个字,第一反应是:这不就是把大数变小嘛,有啥难的?后来真上手做项目,才发现这里面的门道深着呢。你想想看,一个70B的模型,FP32精度下光权重就占280GB,单张A100都塞不下。但你要是直接砍成INT8,模型倒是小了,可精度掉得让你怀疑人生。

所以今天这一讲,咱们就把量化这件事彻底掰扯清楚。我会从最基础的概念讲起,然后带你看看量化到底是怎么影响速度和精度的。嗯,这里要注意,我讲的不是教科书上的定义,而是我在实际项目中踩过的坑和总结的经验。

2.1 什么是量化?说白了就是「降维打击」

量化,本质上是一种数值映射。把连续的、高精度的数值(比如FP32),映射到离散的、低精度的数值(比如INT8)上。

我习惯用一个比喻来解释:

FP32就像用游标卡尺量东西,精度能到毫米级。INT8就像用一把只有256个刻度的尺子,每个刻度代表一个区间。你量出来的结果,只能是这256个刻度中的一个。

所以量化过程,其实就是把浮点数「四舍五入」到最近的整数刻度上。这个过程中,信息丢失是必然的,关键是怎么让丢失的信息对最终结果影响最小。

核心公式(对称量化):

scale = (max_val - min_val) / (127 - (-128))
zero_point = 0  # 对称量化中零点为0
quantized_val = round(float_val / scale)

反量化:dequantized_val = quantized_val * scale

我在项目中遇到过最典型的场景:一个训练好的BERT模型,FP32精度下准确率92.3%。直接做对称量化到INT8,准确率掉到了88.7%。当时客户差点掀桌子。后来我改用非对称量化,配合校准数据集,才把准确率拉回到91.8%。

你看,同样是量化,不同的策略结果天差地别。

2.2 量化如何影响速度?—— 三个层面的加速

量化能加速,这个大家都知道。但具体是怎么加速的?我把它拆成三个层面来讲。

2.2.1 计算层面:INT8比FP32快多少?

直接说结论:在主流硬件上,INT8的矩阵乘法比FP32快2-4倍。

为什么会这样?

  • 指令吞吐更高:现代GPU和CPU都支持INT8的向量化指令。比如NVIDIA的Tensor Core,一个时钟周期能处理64个INT8运算,但FP32只能处理16个。
  • 内存带宽瓶颈缓解:INT8数据量只有FP32的1/4,从显存搬运数据的时间大幅缩短。说白了,计算单元不用等数据了。
  • 缓存命中率提升:同样的缓存大小,能塞下4倍多的INT8参数。这意味着更少的缓存缺失,更少的内存访问。

我的经验: 在实际部署中,INT8推理的加速比通常在1.5x-3x之间。达不到理论4倍的原因,是因为模型中还有LayerNorm、Softmax这些非量化操作,它们依然是FP32的。

2.2.2 存储层面:模型瘦身75%

这个很好理解。FP32是4字节,INT8是1字节。所以模型权重直接从4倍缩小到1倍。

举个例子:

模型 FP32大小 INT8大小 节省
LLaMA-7B ~26GB ~6.5GB 19.5GB
LLaMA-13B ~52GB ~13GB 39GB
LLaMA-70B ~280GB ~70GB 210GB

你想想看,70B的模型,原来需要4张A100才能装下。量化到INT8后,1张A100就够了。这不仅仅是省钱的问题,更是能不能部署的问题。

2.2.3 功耗层面:省电就是省钱

这个很多人会忽略。INT8运算的功耗比FP32低得多。在数据中心里,功耗就是成本。我曾经帮一个客户做量化部署,模型推理速度提升了2.1倍,功耗反而下降了40%。

嗯,这里要提醒一句:功耗下降不是因为计算变少了,而是因为每次计算消耗的能量变少了。

2.3 量化如何影响精度?—— 信息丢失的艺术

量化一定会损失精度,这是物理定律决定的。但损失多少,取决于你怎么量化。

2.3.1 精度损失的来源

我总结为三个「杀手」:

  1. 截断误差:超出量化范围的数值被直接截断。比如你的权重范围是[-10, 10],但量化范围只有[-128, 127],那-10和10之间的数值会被映射到-128和127,中间的信息全丢了。
  2. 舍入误差:浮点数到整数的四舍五入。这个误差通常很小,但累积起来也会影响最终结果。
  3. 异常值:模型权重中偶尔会出现特别大或特别小的值。这些异常值会拉大量化范围,导致正常数值的精度下降。

我曾经踩过的坑: 有一次量化一个视觉模型,发现精度掉得特别厉害。排查了半天,发现是某个卷积层的权重里有一个异常值,比正常值大了100倍。这个异常值把整个量化范围都撑大了,导致正常数值的量化精度极低。后来我用了「异常值裁剪」策略,才把精度拉回来。

2.3.2 精度损失的度量

我们通常用以下几个指标来衡量量化后的精度损失:

  • 准确率下降:分类任务中最直观的指标。比如从92%降到90%,下降了2个百分点。
  • 困惑度增加:语言模型中常用。量化后困惑度增加0.5-2.0都是正常的。
  • BLEU/ROUGE下降:生成任务中常用。量化后下降1-3个点可以接受。

但说实话,这些指标只是参考。真正重要的是:量化后的模型在业务场景中是否还能用?

2.4 量化策略的选择:精度与速度的博弈

既然量化一定会损失精度,那我们的目标就不是「零损失」,而是「可接受的损失」。

我习惯把量化策略分为三个等级:

策略 精度损失 速度提升 适用场景
权重量化(W8A16) 极小(<0.5%) 1.2x-1.5x 对精度要求极高的场景
权重+激活量化(W8A8) 较小(0.5%-2%) 2x-3x 大多数生产环境
全INT8量化 较大(2%-5%) 3x-4x 对速度要求极高,精度可妥协

我个人习惯的做法是:先用权重量化试试水,如果精度损失在可接受范围内,再尝试权重+激活量化。如果还不够,再考虑全INT8。

你可能会问:为什么不直接上全INT8?因为全INT8的部署难度大得多,而且一旦精度掉得太多,调优成本很高。

2.5 量化后的模型长什么样?

为了让你更直观地理解量化,我画了一张流程图,展示了从FP32模型到INT8模型的完整流程。

量化流程示意图 FP32 原始模型 校准数据集 (用于计算scale) 计算量化参数 (scale, zero_point) 执行量化 (权重/激活值) INT8 量化模型 精度验证 (对比FP32结果) 精度不达标,调整策略

这张图展示了我常用的量化流程。注意看那个反馈箭头——精度验证如果不达标,就需要回到量化参数计算阶段,调整策略。比如换用非对称量化、调整校准数据集、或者做异常值裁剪。

2.6 量化后的推理流程

量化后的模型推理,和FP32推理有什么不同?我简单说一下:

# FP32推理流程
输入(FP32) → 权重(FP32) → 矩阵乘法(FP32) → 激活函数(FP32) → 输出(FP32)

# INT8推理流程
输入(FP32) → 量化到INT8 → 权重(INT8) → 矩阵乘法(INT8) → 
反量化到FP32 → 激活函数(FP32) → 量化到INT8 → ... → 输出(FP32)

你看,INT8推理多了「量化」和「反量化」两个操作。这两个操作虽然增加了计算量,但因为矩阵乘法从FP32变成了INT8,整体速度还是大幅提升的。

我的建议: 在实际部署时,尽量把量化/反量化操作融合到相邻的算子中。比如把量化操作融合到前一个算子的输出中,减少显存读写。这个技巧在TensorRT和ONNX Runtime中都有现成的实现。

2.7 什么时候不适合量化?

量化不是万能的。我遇到过几种不适合量化的场景:

  • 小模型:参数量小于100M的模型,量化后精度损失可能超过5%。因为小模型本身信息冗余少,经不起折腾。
  • 对异常值敏感的任务:比如医疗影像诊断、金融风控等。这些任务中,一个异常值可能就是关键信息。
  • 需要高精度输出的任务:比如科学计算、数值模拟。这些任务对数值精度有硬性要求。

嗯,如果你遇到这些场景,建议先做充分的精度验证,再决定是否量化。

2.8 小结

量化,说白了就是用精度换速度。但怎么换、换多少,是一门艺术。

我个人习惯把量化看作一个「调优」过程,而不是一个「转换」过程。你需要反复尝试不同的策略,找到那个精度和速度的平衡点。

最后送大家一句话:没有最好的量化策略,只有最适合你业务的量化策略。


公众号:蓝海资料掘金营,微信deep3321