Skip to content

约 5 分钟阅读

05. FP8、FP4 与整数量化 ​

从 FP32 到 FP16,每个数的空间减半;继续变成 8 位或 4 位,可用组合就更少了。4 位一共只有 16 种编码,怎样用它们保存一组有大有小的参数?这一篇用整数刻度和一把可伸缩的尺解释缩放,再比较 FP8、FP4 的做法。

INT4:四位怎样保存负数 ​

INT 是 Integer,也就是整数。INT4 用四位保存一个有符号整数,常用的读取规则叫补码:从左到右的位权为 −8、4、2、1。最高位承担一个负位权,其余位仍是正位权。

例如 1011 读作 1 × (−8) + 0 × 4 + 1 × 2 + 1 × 1 = −5。最高位为 0 时,范围是 0 到 7;最高位为 1 时,范围是 −8 到 −1。合起来就是 −8 到 7,共 16 个整数。

INT4:逐段标出存储位数、示例编码和读回过程

INT8:相同规则,多留四位 ​

INT8 的最高位位权变成 −128,其余七位从 64 递减到 1。11111011 的低七位相加为 123,所以读作 −128 + 123 = −5。完整范围扩大到 −128 到 127。

INT8:逐段标出存储位数、示例编码和读回过程

INT4 和 INT8 的位都用来表示整数,没有指数和小数区域。那么模型中的 0.3 怎样保存进去?我们给整数刻度配一把可以缩放的尺。

给整数配上缩放因子 ​

下面选择对称 INT4 教学方案,只用 −7 到 7 这 15 个整数,留下 −8 的编码不用,让正负两侧的刻度对称。假设要保存的参数都落在 −2 到 2,把最大正刻度 7 对应到 2,刻度间距就是:

scale = 2 / 7 ≈ 0.285714

保存一个值时,先除以 scale,舍入成整数,再限制在编码范围内;读取时用整数乘回 scale。例如保存 0.3:

0.3 / (2/7) = 1.05 → 整数 1 → 1 × (2/7) ≈ 0.285714

把原始值映射到这一组有限刻度的过程,称为量化。保存下来的内容是整数编码与一组数共用的 scale。这里选择零点为 0 的对称方案;其他方案还可能保存一个零点,用来移动整把尺的位置。

一个大数,为什么会影响旁边的小数 ​

现在同一组里突然出现 20。如果把它也包进来,scale 就变成 20/7 ≈ 2.857143。原本的 0.3 除以新 scale 后约为 0.105,舍入成 0,细节消失了。

在下面调节待保存的数,打开“大值 20”,观察刻度怎样拉开。再把大值分到另一组,小数这一组就能重新使用更细的刻度。

-202上方:原始值红点:恢复值
刻度间距 scale
0.285714
保存的整数
1
恢复的数
0.285714

绝对误差 0.014286。当前组覆盖 −2 到 2,共用一个 scale。

这就是分组量化的一个动机:让相近范围的数共用一把尺,减少极端值对整组的影响。分得更细也要保存更多 scale,实际模型大小会增加。另一种选择是固定较小范围并裁掉极端值:若范围仍为 −2 到 2,20 最多只能恢复为 2;它承担的误差就很大。

实验切换分组时,会从原始值重新量化,所以 0.3 能重新得到整数 1,再恢复成约 0.285714。如果手里只剩上一次量化后的整数 0,就无法从中找回原来的 0.3。实际模型通常按张量位置或通道分组,也未必能把每个大值单独放到另一组。

校准会用有代表性的输入观察数值分布,帮助决定刻度与裁切范围。用短句校准、上线却处理长音频或长文档时,分布可能变化,所以样本需要覆盖实际任务。

FP8 和 FP4 把浮点刻度缩小了 ​

整数配固定 scale 时,一组内部通常等间距;浮点数的间距随指数变化。FP8 把符号、指数、小数部分都塞进 8 位。名称中的 E 表示指数位数,M 表示保存的小数位数,再加一位符号,就得到总位数。

FP8 E4M3FN:一字节里也能放浮点数 ​

1 位符号、4 位指数、3 位小数部分,指数偏移量为 7。保存 1.25 时,小数部分仍写 010,指数编码为 0111。它的最大有限值是 448;FN 表示采用有限数与 NaN 的编码约定,指数全 1 时也有一部分位置继续保存有限数。

FP8 E4M3FN:逐段标出存储位数、示例编码和读回过程

FP8 E5M2:多一位指数,少一位小数 ​

指数扩大为 5 位,偏移量变成 15;小数部分缩成两位,刚好能保存 1.25 的 .01₂。最大有限值扩大到 57344,同一数量级内的刻度也更疏。

FP8 E5M2:逐段标出存储位数、示例编码和读回过程

FP8 也常配 scale,把一组数放到格式适合的范围内。缩放后还要舍入到浮点格式自己的刻度。另一组 FP8 名称带有 FNUZ,其指数偏移量和特殊值编码有所调整,完整图解放在FP8 变体中。

FP4 E2M1:四位里只剩一位小数 ​

1 位符号、2 位指数、1 位小数部分,指数偏移量为 1。这次用 1.5 做例子:0 | 01 | 1 读作 (1 + 1/2) × 2^0 = 1.5。

FP4 E2M1:逐段标出存储位数、示例编码和读回过程

1.25 落在 1 与 1.5 的正中间,已经没有足够的小数位精确保存它。采用就近、平局取偶的舍入时,它会变成 1。E2M1 的非负幅值只有 0、0.5、1、1.5、2、3、4、6,加上负号形成另一半编码,通常需要结合细分组缩放来保存模型数据。

NVFP4、MXFP4 进一步规定了一组数怎样共用 scale。比如 MXFP4 每 32 个四位值配一个八位 scale,平均每个值需要 4 + 8/32 = 4.25 位;NVFP4 常见的 16 值分组使用八位块级 scale,还会配张量级 scale。对应的分组存储图把这笔额外空间也画了出来。

W4A16 写的是哪些数 ​

W 指权重,A 指激活。W4A16 表示权重用 4 位方案,激活用 16 位;还需要继续确认 4 位是 INT4、FP4 还是其他编码,16 位是 FP16 还是 BF16。累加精度和 KV 缓存另有配置。

加载量化模型时,计算程序可以把编码还原成较高精度值再参与乘法,称为反量化。也可以把反量化与矩阵计算融合,减少额外读写。是否存在适合该设备的实现,会直接影响速度。

把数字压得更短,需要同时安排编码、scale 和执行方式。下一篇怎样选择与验证精度会把这几件事放在一张实际决策清单中,完成从格式名称到可验证配置的最后一步。

别急,先让缓存热一下。