第 1 章 课程导入:混合精度训练的定义、发展背景、核心价值与整体课程框架
当你第一次在单卡上训练一个十亿参数级别的模型时,最直观的瓶颈往往不是显存容量,而是显存带宽与算力利用率。FP32 训练虽然数值稳定,但每个参数、梯度、优化器状态都占用 4 字节,激活值更是显存大户。混合精度训练(Mixed Precision Training)正是为解决这一矛盾而生的工程实践:它让模型在关键计算路径上使用 FP16/BF16 加速,同时保留 FP32 主权重以维持数值稳定。
一、什么是混合精度训练
混合精度训练并不是“把 FP32 全部换成 FP16”这么简单。它的核心思想是:在计算密集、对精度不敏感的部分使用低精度,在参数更新、损失累加等对数值范围敏感的部分保留高精度。典型做法是维护一份 FP32 主权重(Master Weight),前向与反向传播使用 FP16/BF16,梯度在更新前被放大并转换回 FP32,再作用于主权重。
其中损失缩放是混合精度能否稳定收敛的关键。FP16 的最小正规数约为 6.1e-5,很多梯度值远小于该阈值,直接反向传播会变成 0。动态损失缩放通过自动调整缩放因子,让梯度在 FP16 可表示范围内被保留,再在更新前还原。
二、发展背景:从 FP32 到混合精度的必然
2017 年 NVIDIA 在 Volta 架构中引入 Tensor Core,FP16 矩阵乘加吞吐达到 FP32 的 8 倍以上。但早期直接使用 FP16 训练常出现梯度下溢、权重更新失效、Loss 震荡等问题。2018 年 NVIDIA 与百度联合发表《Mixed Precision Training》,系统提出 FP32 主权重 + 损失缩放的方案,使混合精度在 ResNet、BERT 等模型上达到与 FP32 几乎一致的精度。
随后 BF16 出现,它保留 FP32 的 8 位指数,动态范围与 FP32 相同,几乎不需要损失缩放,在 A100、H100 及国产加速卡上迅速普及。今天,混合精度已成为大模型训练的默认配置,与 ZeRO、梯度检查点、FlashAttention 等技术共同构成现代训练栈。
三、核心价值:为什么值得投入学习
| 维度 | FP32 训练 | 混合精度训练 | 收益来源 |
|---|---|---|---|
| 显存占用 | 高 | 降低约 30%~50% | 激活值、梯度用 FP16 存储 |
| 计算吞吐 | 基准 | 提升 2~8 倍 | Tensor Core 低精度矩阵乘 |
| 通信开销 | 高 | 降低约一半 | 梯度以 FP16 通信 |
| 收敛精度 | 基准 | 可持平或略优 | 损失缩放 + 主权重 |
| 工程复杂度 | 低 | 中高 | 需处理溢出、缩放策略 |
四、典型场景与常见误区
混合精度最适合计算密集、显存受限、矩阵维度较大的场景,例如 Transformer 预训练、大规模推荐模型、视觉检测模型。但在小模型、小批量或含大量归约操作的模型中,收益可能有限,甚至因溢出处理带来额外开销。
另一个误区是认为 BF16 可以完全替代损失缩放。BF16 动态范围大,确实很少溢出,但其尾数只有 7 位,梯度精度较低,在部分任务上仍需配合主权重与谨慎的超参设置。
五、整体课程框架
本课程共 30 章,围绕“原理—配置—实操—排障—复盘”展开。前段建立混合精度与损失缩放的理论基础;中段进入 PyTorch AMP、GradScaler、BF16 与分布式训练配置;后段覆盖溢出诊断、性能剖析、精度回归与生产级训练模板。
# 典型 PyTorch 混合精度训练骨架
scaler = torch.cuda.amp.GradScaler()
for data, target in loader:
optimizer.zero_grad()
with torch.cuda.amp.autocast(dtype=torch.float16):
output = model(data)
loss = criterion(output, target)
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()
完成本章后,你应当能用自己的话解释:混合精度为什么需要 FP32 主权重、损失缩放解决什么问题、BF16 与 FP16 的取舍差异,以及本课程将如何带你从“能跑”走向“跑得稳、跑得快”。