Skip to content

混合精度训练全指南:FP16/BF16/FP8 的选择与工程 ​

说明:本篇为综述/无第一手实验数据,采用公开实践与硬件规格路线。

实验目标 ​

混合精度不是"开个 AMP 就行"——FP16 的溢出问题、BF16 的精度取舍、FP8 的新时代(训练+推理)、以及它们与损失缩放/稳定性/检查点的相互作用,都是工程决策。本篇目标:拆解混合精度训练的完整框架——AMP 机制与 loss scaling(为什么需要缩放)→ FP16/BF16/FP8 的精度画像与选择矩阵 → 训练中的精度策略(何时降精度、何时不能降)→ 与检查点/稳定性的衔接。读完能回答:我的训练该用哪种精度、AMP 怎么配、FP8 值不值得上。

代码逐段拆解 ​

第一段:AMP 与 loss scaling ​

python
# PyTorch AMP(Automatic Mixed Precision)标准用法
scaler = torch.cuda.amp.GradScaler()          # 梯度缩放器

for x, y in loader:
    with torch.autocast(device_type="cuda", dtype=torch.bfloat16):
        loss = model(x, y)                    # 前向:自动混合精度
    scaler.scale(loss).backward()             # 缩放后再反传
    scaler.step(optimizer)                    # 反缩放后更新
    scaler.update()                           # 动态调整缩放因子

要点:

  1. AMP 只在前向/反向自动选精度:算子级自动选择(矩阵乘/卷积用低精度,归一化/softmax 保持高精度),权重仍以 FP32 主副本保存——"混合精度"的混合指的是这个。
  2. loss scaling 解决 FP16 的梯度下溢:FP16 最小正数 ~6e-5,小梯度直接归零;把 loss 乘以缩放因子(如 2¹⁶)再反传,梯度放大后不丢失,更新前再除回。BF16 不需要 loss scaling(指数位与 FP32 相同,无下溢问题)——这是 BF16 在训练中的关键优势。
  3. scaler.update() 动态调缩放:出现 inf/NaN 时缩放因子减半并跳过该步更新(step 内部处理),稳定后逐步恢复——loss scaling 是 FP16 训练稳定的核心机制。

第二段:三种精度的选择 ​

python
# FP16:老牌,需 loss scaling,动态范围小
# BF16:训练主流,无需 loss scaling,尾数少(精度略降)
# FP8:新一代,训练+推理都能用,需要更细的缩放与特殊处理

# 选择矩阵(经验口径):
# 常规 LLM 预训练/微调 → BF16(简单、稳)
# 需要省显存/提速且能接受微降 → FP16 或 FP8(显存减半)
# 小模型/低动态范围任务 → FP16 可行

要点:

  • 训练主推 BF16:与 FP32 相同的动态范围(无溢出/下溢),无需 loss scaling,尾数 7 位(比 FP16 的 10 位少)导致精度略降但多数训练任务可接受——"简单+稳"让 BF16 成为大模型训练默认。
  • FP16 的优势与代价:显存更小(FP32 一半)、部分算子更快,但动态范围小(大值溢出、小值下溢)必须 loss scaling;适合"明确需要小显存/更快"的场景。
  • FP8 是前沿:E4M3(权重/激活)与 E5M2(梯度)两种格式配合,显存再减半、吞吐再提升,但需要逐张量缩放(比 loss scaling 更细)与硬件/框架支持成熟度——新项目评估,生产大规模训练暂以 BF16 为稳妥基线。

原理讲解 ​

精度画像对比 ​

精度指数位尾数位动态范围训练要点
FP32823大主副本/基准
FP16510小需 loss scaling
BF1687大(同 FP32)无需缩放,精度略降
FP8(E4M3)43很小需逐张量缩放
FP8(E5M2)52较小梯度用

核心认知:精度选择的本质是"动态范围 vs 尾数精度"的权衡——FP16 输在动态范围(溢出/下溢)、BF16 输在尾数(精度略降)、FP8 两者都紧(需细粒度缩放)。训练(梯度传播敏感)与推理(前向即可)对精度的容忍度不同:推理可以更低精度(12 章量化篇),训练保守(BF16 起步)。

与稳定性/检查点的衔接 ​

  • 稳定性:BF16 训练出现 loss spike 时,先排查数据/学习率(10 章 spike 篇),不要先怀疑精度——除非复现实验证明换 FP32 改善。
  • 检查点:主权重以 BF16/FP32 保存(11 章 mixed-precision-checkpoint 篇的精度处理),优化器状态(Adam 的一阶/二阶矩)需要更高精度——检查点精度与训练精度是两个决策。

实验结果 ​

(估算口径,非实测;典型 LLM 训练)

精度显存(相对 FP32)训练吞吐(相对)稳定性
FP16 + scaling~0.5×1.5-2×需缩放管理
BF16~0.5×1.5-2×好(无需缩放)
FP8~0.25×2-3×需细缩放,成熟度低

工程启示 ​

  1. 默认 BF16:大模型训练从 BF16 起步,简单稳定;FP16/FP8 有明确收益(显存/速度)再换。
  2. FP16 必须配 loss scaling:GradScaler 三件套(scale/step/update)是标准,别只开 autocast 不配缩放。
  3. 检查点精度独立决策:主权重低精度、优化器状态高精度——别把"训练精度"和"检查点精度"混为一谈。
  4. FP8 先小规模验证:评估硬件/框架支持与逐张量缩放实现,收益(显存减半)明确且验证通过再上生产。

下一篇预告:单卡精度与效率讲完,看产业级落地形态——"数字孪生与工业仿真:超算、AI 代理模型与实时数据的闭环"。

AI-HPC 智算超算专家 · Contact: openaihpc@gmail.com