FP8 转换原理
本文说明项目中float转换为 FP8 的数学原理和处理逻辑。项目支持两种 OFP8 格式:E4M3 和 E5M2。
FP8 格式
FP8 由符号位、指数位和尾数组成:
| 格式 | 符号位 | 指数位 | 尾数位 | 指数偏置 |
|---|---|---|---|---|
| E4M3 | 1 | 4 | 3 | 7 |
| E5M2 | 1 | 5 | 2 | 15 |
正规数的值为:
(-1)^符号 × (1.尾数) × 2^(指数 - 偏置)次正规数没有隐含的最高位 1,其值为:
(-1)^符号 × (0.尾数) × 2^(1 - 偏置)FP8 的 8 位编码顺序是符号位、指数位、尾数位。
转换的总体流程
将一个较宽的浮点数转换为 FP8 时,依次完成以下步骤:
- 识别 NaN、Infinity 和零。
- 提取源数的符号、指数和有效尾数。
- 将源指数换算为目标 FP8 的指数范围。
- 判断结果应使用正规数还是次正规数表示。
- 截取目标格式需要的尾数位。
- 使用
roundTiesToEven舍入被丢弃的位。 - 处理尾数进位以及由此产生的指数变化。
- 根据舍入后的结果判断溢出。
- 重新组合符号、指数和尾数字段。
OCP OFP8 规范要求有限数必须先舍入,再判断舍入后的幅值是否溢出。
特殊值
NaN 转换为目标格式的 NaN 编码。NaN 的具体尾数编码和符号处理属于实现细节。
Infinity 的结果取决于格式和饱和模式:
| 输入 | 饱和模式 | 非饱和模式 |
|---|---|---|
±Infinity转 E5M2 | ±最大有限值 | ±Infinity |
±Infinity转 E4M3 | ±最大有限值 | NaN |
正零和负零都保留源数的符号位。
FP32 有效数和指数的转换
FP32 正规数包含 23 位显式尾数,并带有一个隐含的最高有效位 1。因此转换时需要把它看成 24 位有效数。
FP32 的无偏指数等于其编码指数减去 127。目标 FP8 的编码指数则等于这个无偏指数加上目标格式的偏置:E4M3 加 7,E5M2 加 15。
目标指数为正时,结果进入正规数路径;目标指数不为正时,结果进入次正规数路径。
正规数路径
正规数保留一个隐含的最高位 1,以及目标格式允许的尾数位。FP32 多出来的低位不能直接丢弃,而要根据舍入规则处理。
roundTiesToEven
舍入到最近值、相等时取偶数使用三个信息:
- Guard 位:被丢弃部分的第一位。
- Sticky 位:Guard 后面的位中是否至少有一个 1。
- 保留部分的最低位:用于判断精确中点时当前候选值是否为偶数。
判断规则如下:
| 条件 | 结果 |
|---|---|
| Guard 为 0 | 小于半个间隔,不进位 |
| Guard 为 1 且 Sticky 为 1 | 大于半个间隔,进位 |
| Guard 为 1、Sticky 为 0,保留部分最低位为 0 | 正好在中点,不进位 |
| Guard 为 1、Sticky 为 0,保留部分最低位为 1 | 正好在中点,进位 |
这里的“偶数”指保留结果最低位为 0,而不是要求最终数值为整数。
尾数进位
舍入可能使尾数从全 1 进位为更高一位。例如1.111舍入后变成10.000。此时需要将尾数重新规格化为1.000,同时指数增加 1。
次正规数路径
当目标指数不足以表示正规数时,使用次正规数。次正规数没有隐含的最高位 1,因此源有效数需要根据指数差额额外右移。
额外右移后仍使用同样的roundTiesToEven规则:
- 舍入结果为零时,生成带符号的零。
- 舍入结果刚好跨过次正规数上限时,提升为最小正规数。
- 其他情况生成指数为零的次正规数。
因此,最小正规数和最大次正规数之间的边界也必须纳入测试。
溢出处理
溢出判断必须使用舍入和规格化之后的结果。不能仅根据原始输入是否大于最大有限值来提前判断。
E5M2 的全 1 指数编码用于特殊值,因此舍入后的指数达到特殊值范围时发生溢出。E4M3 的全 1 指数包含部分有限编码,但全 1 指数和全 1 尾数组合是 NaN,因此需要单独排除该编码。
发生溢出后:
| 格式 | 饱和模式 | 非饱和模式 |
|---|---|---|
| E5M2 | 最大有限值 | Infinity |
| E4M3 | 最大有限值 | NaN |
例如,E4M3 的最大有限值为 448。输入 450 或 464 可能在舍入后仍得到 448,所以不能在舍入前直接将它们判定为溢出。E5M2 也存在同样的最大有限值边界。
数值示例
在 E4M3 的[1, 2)区间,相邻数包括 1.25 和 1.375:
- 1.3 更接近 1.25,因此舍入为 1.25。
- 1.3125 正好位于两者中间。由于 1.25 的保留尾数最低位为 0,结果选择 1.25。
这个例子说明中点并不固定向上或向下,而是由保留结果的最低位决定。
与指令集的关系
当前 BF16 到 FP8 的标量和向量转换指令,都会先把 BF16 数值恢复为较宽的浮点值,再按照同一套 FP8 转换逻辑处理。
FP8 加、减、乘运算的结果也需要重新编码为 FP8,因此它们同样会经过尾数舍入、次正规数处理和溢出处理。
验证重点
回归测试应覆盖:
- E4M3 和 E5M2 的正数、负数、零、NaN 和 Infinity。
- 每一对相邻 FP8 数值的精确中点及中点两侧的输入。
- 最小次正规数、最大次正规数和最小正规数的边界。
- 尾数进位导致指数增加的边界。
- 最大有限值附近的输入。
- 饱和和非饱和两种溢出模式。
- BF16 标量转换、向量转换和 FP8 算术结果写回。
目录