简介:本文面向开发者与技术选型人员,系统讲解大模型中FP8(8位浮点)的定义、结构变体、设计动机与典型用法。读者将理解E4M3与E5M2的差异、FP8为何能在几乎不损失收敛性的前提下减半显存并提升吞吐,以及它在训练与推理流程中的适用边界与注意事项。
在阅读大模型技术文档或显存估算表时,”FP8”这个词出现的频率越来越高。它既出现在训练配置里,也出现在推理服务的精度选项中,还常与”显存减半””吞吐翻倍”这类描述绑定出现。但对不少开发者来说,FP8 更像一个模糊的缩略词:它到底是一种数据类型、一种量化方案,还是一种计算模式?本文从定义出发,逐层拆解这一概念。
FP8 是”8 位浮点数(8-bit Floating Point)”的统称,指用总共 8 个比特来表示一个浮点数值的数值格式。与之对照,常见的 FP32 占 32 位、FP16 与 BF16 各占 16 位。位宽减半意味着在相同的显存容量下可以容纳约两倍的参数或激活值,也意味着在支持该格式的硬件上,矩阵运算的数据通路更窄、单位时间内可处理的元素更多。
需要强调的是,FP8 并不是一个单一、固定的格式。它是一类格式的集合,具体如何划分符号位、指数位和尾数位,由硬件与软件栈共同约定。目前业界主流的两类变体是 E4M3 与 E5M2,前者偏重精度、后者偏重动态范围。
从使用视角看,FP8 更像一种”计算与存储时的精度选择”:模型参数、激活值、梯度可以在训练或推理的某些环节以 FP8 参与存储和运算,而在需要高精度的环节(如梯度累积、归一化统计、损失计算)仍保留更高精度。理解 FP8,本质上是理解”哪些数据可以降精度、降多少、代价是什么”。
大模型的规模增长带来两个直接压力。其一是显存压力:参数量、激活值、优化器状态共同占用大量显存,位宽每降低一档,能装载的模型规模或批量大小就显著提升。其二是带宽与算力压力:矩阵乘法的吞吐在很大程度上受限于数据搬运与计算单元的数据位宽,更窄的格式通常能带来更高的理论吞吐。
FP8 的价值正来自这两点:相比 16 位格式,理论显存占用减半、计算吞吐提升;而大量实践表明,在配合适当的缩放策略时,训练收敛曲线与 16 位基准格式可以非常接近。这使得 FP8 从”实验性格式”逐步成为前沿模型训练与推理的常规选项。
不过,位宽降低并非没有代价。8 位能表达的离散数值非常有限,指数位决定了能覆盖多大范围的数值,尾数位决定了同一范围内的分辨精度。若直接把大幅值或小幅值的数据塞进 FP8,就会出现溢出(上溢为无穷)或下溢(被截断为零),进而破坏梯度或激活的分布。因此 FP8 的可用性高度依赖”缩放(scaling)”这一配套机制,这也是后文原理部分的重点。
一个浮点格式通常由三部分构成:符号位(决定正负)、指数位(决定数量级、即动态范围)、尾数位(决定有效数字、即精度)。在总位宽固定的前提下,指数位与尾数位是此消彼长的关系:指数位多则能表示更大和更小的数,但同数量级内的分辨更粗;尾数位多则数值更精细,但可表示的范围收窄。
以 16 位格式为例,BF16 采用 1 位符号、8 位指数、7 位尾数的划分。它与 32 位单精度共享相同的 8 位指数宽度,因此动态范围几乎一致,只是尾数精度较低。这种”范围优先”的设计使它在训练中不易出现梯度溢出或下溢,成为许多训练任务的稳定基准。
FP8 的两种常见划分方式体现了不同的取舍:
这种”前向用 E4M3、反向用 E5M2”的分工并非硬性规定,而是一种常见的工程权衡:前向数据通常分布较集中,精度损失更敏感;梯度则可能跨越多个数量级,范围不足更容易造成溢出。
在 FP8 之外,业界也在探索 4 位浮点格式。这类格式的典型设计思路是分层缩放:基础元素采用极窄的位域(如 1 位符号、2 位指数、1 位尾数),单值可表示的离散数值仅十余个,精度有限;随后用”微块共享缩放因子”的方式补偿——例如每若干元素组成一个微块,共享一个 8 位浮点格式的缩放因子,该缩放因子支持非 2 的幂的分数级缩放,从而降低量化误差;再在张量级别叠加一个更高精度的全局缩放因子,弥补局部缩放无法覆盖的整体偏移。
按这种分层设计,每个元素的实际等效位宽约为 4 位加上微块缩放分摊的少量位,仍显著低于 FP8 与 16 位格式。这一思路说明了低精度格式的通用规律:位宽越低,越依赖分层、分块的缩放体系来维持可用性。理解这一点,有助于把握 FP8 在整个低精度谱系中的位置——它处在”位宽已明显收窄、但仍可较多依赖单一缩放策略”的区间。
FP8 的使用不是简单地”把数据类型换掉”,而是一套包含缩放、转换与误差控制的流程。可以用一个示意性伪代码概括前向传播中的典型步骤:
# 以张量级缩放为例(示意,非具体接口)scale = compute_scale(fp32_tensor) # 依据张量幅值分布计算缩放因子fp8_tensor = quantize(fp32_tensor / scale) # 缩放后转换为 FP8# 计算阶段使用 FP8 参与矩阵运算output = matmul(fp8_weight, fp8_activation)# 累加与结果回写通常保持更高精度fp32_output = dequantize(output) * scale
关键点有三:
第一,缩放因子的作用是”把数据搬到 FP8 能良好表示的区间”。由于 FP8 的指数范围有限,直接转换容易溢出或下溢,先除以一个缩放因子把幅值压缩到合适区间,计算完成后再乘回来,可以在不改变数值语义的前提下利用低精度通路。
第二,累加通常保留高精度。矩阵乘法的中间累加若也用低精度,误差会快速累积,因此常见做法是低精度输入、高精度累加,再在输出端做反缩放。
第三,不同环节可选用不同变体。如前述,前向可用精度更细的 E4M3,反向梯度可用范围更宽的 E5M2,从而在整体上兼顾精度与稳定性。
FP8 是用 8 个比特表示浮点数的数值格式统称,以 E4M3 与 E5M2 为主要变体,分别侧重精度与动态范围。它的核心价值在于以位宽减半换取显存与吞吐收益,而其可用性建立在缩放机制与混合精度调度之上。理解 FP8,关键在于把握三点:它是一种需要配套缩放策略的低精度通路,而非可直接替换所有环节的万能格式;它在训练与推理中的适用边界不同;它与 16 位格式、整数量化、更低位宽格式各有分工。明确这些边界,才能在技术选型时做出与自身模型规模和业务目标相匹配的判断。