浮点精度及其对模型推理的影响

浮点精度及其对模型推理的影响

💡 原文英文,约1900词,阅读约需7分钟。
📝

内容提要

本文讨论浮点精度对模型推理的影响。浮点数由符号、指数和尾数组成,降低精度需权衡范围、精度与内存。FP16尾数多但范围小,BF16范围接近FP32但精度低;FP8、FP4需配合缩放。低精度未必更快,取决于硬件内核支持。可通过to()或加载时指定dtype转换模型,归一化、softmax等敏感操作宜用FP32混合精度。评估应从内存、性能和质量三方面进行,并记录软硬件配置。

🔎

延伸解读

低精度不等于更快:硬件内核是关键

文章强调,降低精度能否加速推理,取决于目标硬件是否有高效的内核支持。如果硬件缺乏对应格式的优化内核,低精度格式可能运行缓慢,甚至因插入额外转换而抵消预期收益。因此,选择精度格式时,不能只看位数,而应优先确认部署硬件和软件栈对该格式的实际支持情况,并通过代表性前向传播和性能分析来验证。

FP16与BF16:范围与精度的取舍

FP16尾数更多,能更精细地区分邻近值,但指数位少,动态范围有限,激活值较大时容易溢出。BF16指数位与FP32相同,范围更宽,但精度较低。对于Transformer激活,BF16的宽范围常能避免FP16的溢出问题。不过,最佳选择仍取决于模型、内核和硬件,不能一概而论。

混合精度:敏感操作保留FP32

模型不必所有部分使用同一精度。矩阵乘法可用FP16或BF16,而归一化、归约、logits等敏感操作可保留FP32,以降低数值误差。文章提醒,softmax需先减去最大logit再指数化,归约应在更宽类型中累加。但不要随意修改预训练模型模块,否则可能引发类型不匹配或额外转换开销,应使用模型支持的混合精度路径并验证输出。

评估精度变化:内存、性能与质量

精度调整应从三方面评估:内存(参数存储、峰值分配、KV缓存容量)、性能(预填充延迟、解码延迟、真实批次和序列长度下的吞吐)、质量(困惑度、任务指标、代表性提示的生成对比)。调试时除解码文本外,还应比较输出logits,因为贪婪输出可能相同但logits已变。此外,低精度权重只按转换张量比例节省内存,若KV缓存占大头,总内存不会减半。

❓

Q&A

FP16和BF16有什么区别?哪个更适合Transformer推理?

FP16和BF16都是16位格式,但FP16尾数更多,能更精确地区分相近值;BF16指数位与FP32相同,动态范围更大。对于Transformer激活值,BF16的宽范围常能避免FP16可能遇到的溢出。但最佳选择仍取决于模型、内核和硬件。

降低模型精度一定能加快推理速度吗?

不一定。低精度格式可能节省内存,但如果目标硬件缺乏合适的内核,运行速度反而可能变慢。此外,不支持的运算可能失败、回退到慢速实现或插入额外转换,从而抵消预期的加速。因此需要实际测试代表性前向传播并检查性能分析器。

如何将PyTorch模型转换为半精度(如FP16)?

可以使用`.to(dtype=torch.float16)`转换模型参数和缓冲区。对于预训练模型,建议在加载时直接指定dtype,例如使用Hugging Face的`from_pretrained(..., dtype=torch.float16)`,以避免先加载FP32模型再转换,从而节省大模型的内存。

哪些操作在低精度推理中需要特别小心?如何用混合精度处理?

归一化、softmax、归约等操作对数值范围敏感,容易溢出或下溢。混合精度可以在矩阵乘法中使用FP16/BF16,而将这些敏感操作保留在FP32。例如,在softmax中先减去最大logit再指数化,并用更宽的dtype累加。可以显式将特定操作转换为FP32,同时保持边界dtype一致。

评估精度变化对模型推理的影响时,应该测量哪些方面?

应从三个维度评估:内存(参数存储、峰值内存、KV缓存容量)、性能(预填充延迟、解码延迟、吞吐量)、质量(困惑度、任务指标、生成结果对比)。同时记录硬件和软件配置,并遵循基准测试规则,如预热、同步设备、区分预填充和解码。

FP8和FP4格式在模型推理中有什么特点?使用时需要注意什么?

FP8(如E4M3和E5M2)进一步减少内存,但8位无法同时提供宽范围和高精度,通常需要外部缩放信息。FP4位数更少,不能直接替代FP16,需配合块缩放、校准或训练配方(如MXFP4、NVFP4)。使用前必须确认运行时和硬件是否支持特定格式。

🏷️

标签

➡️

继续阅读