免费技术解读

BF16和FP16都是16位,为什么表现不同:数值范围、精度与混合精度分开看

从指数位和小数位解释BF16与FP16的区别,用假设计算区分溢出与舍入,再按硬件、算子和训练流程核对混合精度配置。

阿军图解产业 · AI 辅助整理 · · 约 4 分钟阅读

图解产业阿军编辑 · AI 辅助整理与编辑核查

BF16把更多位留给指数,能覆盖更宽的数值范围;FP16把更多位留给有效数字,在共同覆盖的同一数量级内,刻度通常更细。两者都是16位,不代表能表示同一批数字,更不能直接推出谁的模型效果更好、运行更快。

理解选型,先拆开三个问题:数值会不会超出范围,相邻数值能分多细,以及计算流程实际在哪些地方使用这种格式。

16个位怎样分配

浮点数可以粗略理解为“有效数字乘以二的某个次方”。符号位区分正负,指数控制数量级,小数部分决定这个数量级内的细分程度。

格式 符号位 指数位 显式小数位 主要取舍
FP16 1 5 10 范围较窄,刻度较细
BF16 1 8 7 范围较宽,刻度较粗
FP32 1 8 23 作为更高精度的对照

这里的小数位也常被称为尾数位;正规数还有一个隐含的最高有效位。BF16与FP32具有相同的指数范围,但小数位少得多,不能理解为“用一半空间完整保留FP32”。位分配依据NVIDIA Transformer Engine格式说明。

“范围”像尺子能量多长,“精度”像相邻刻度隔多远。不过浮点刻度不是固定间距:数量级变大,绝对间距也随之变大。

两个假设计算:装不下与分不清

以下是按格式推导的说明性计算,不是设备实测,也不代表模型指标。

例一:在1附近比较舍入。 在区间[1, 2)内,FP16相邻可表示数的间隔为2⁻¹⁰,即0.0009765625;BF16为2⁻⁷,即0.0078125。假设按最近值舍入,1.001转为FP16约是1.0009765625,转为BF16则是1。

这个例子说明:数字虽然没有超出范围,细小差异仍可能丢失。它不说明“FP16训练一定更准确”,因为模型误差还取决于后续计算与更新方式。

例二:比较平方结果的范围。 假设残差是300,平方为90000。FP16最大有限值为65504;如果平方结果必须以FP16保存,按通常的最近值舍入会溢出为无穷大。BF16可以容纳这一数量级,但90000仍不一定被精确表示。FP16范围及溢出风险可参照PyTorch AMP梯度缩放说明。

不能因此断言“FP16输入的损失计算一定溢出”:框架可能把该算子提升到FP32。排查时要看出问题那一步的实际数据类型,而不是只看模型配置名称。

混合精度不等于把所有东西转成16位

PyTorch的autocast按算子选择计算类型;启用它与手动把整个模型转换成half()或bfloat16()不是同一种操作。官方用法也明确区分这两条路径。具体策略应查设备及版本对应的autocast文档。

读一份配置时,建议画出四格:参数存储、算子计算、中间结果、优化器更新。分别填写数据类型,不要只写一个“BF16训练”。其中还可能存在FP32参数或优化器状态,所以16位计算不能直接换算成整套训练显存减半。

梯度缩放主要用于缓解FP16小梯度下溢:先放大损失,使反向传播的梯度也放大,再在更新前还原。它不会增加小数位,也不是修复所有NaN的开关。BF16范围较宽,通常不因同样的小梯度范围问题需要缩放,但仍须遵循实际训练实现。

训练还涉及反向传播和参数更新,推理则要按部署任务检查输出质量。两种场景的检查重点可结合训练与推理的区别理解,不要把一次推理能运行当作训练稳定的证明。

用这张表检查配置与故障

观察到的问题 优先核对 不宜直接得出的结论
某步首次出现inf或NaN 输入范围、算子类型、首个异常位置 只要换BF16就能修好
数值有限但任务效果下降 与基线的误差、敏感算子、更新配置 小数位多就必然效果好
开启低精度后仍很占显存 参数、激活、梯度、优化器状态分别占多少 所有张量都已变成16位
运行速度没有改善 硬件支持、实际内核、数据形状、瓶颈 支持该格式就一定加速

性能比较还要分清容量与数据搬运速度,可以接着看显存容量和带宽的区别。如果讨论的是把权重映射到更低位整数表示,应转到INT4与INT8量化指南;那不是本篇两个浮点格式的同一项比较。

实际验证时,先固定模型、数据和批量,保留较高精度基线;一次只调整一套精度策略,记录任务指标、异常数值、峰值显存与耗时。发现异常就定位最早出现差异的环节,再决定局部保留高精度还是调整流程。最终选择应由这份记录支持,而不是由“都是16位”或“范围更大”替你决定。

文中算例用于解释原理,具体参数请按引用资料与产品条件核对。发现问题,可将文章链接与依据发送至 support@packscena.com。

查看全部产业指南 →