标准回答
核心机制
混合精度同时使用低精度(fp16 或 bf16)和单精度(fp32):
- fp16/bf16 计算:前向、反向中的矩阵乘等用半精度,激活/梯度显存约减半,并能命中 GPU 的 Tensor Core 大幅提速。
- fp32 主权重:单独保存一份 fp32 参数做更新。半精度下极小的更新量会被舍入丢失,fp32 master weights 保证更新精度。
- Loss Scaling:fp16 的可表示范围窄,小梯度容易下溢为 0。把 loss 放大一个 scale 再反传,梯度同比放大躲过下溢,更新前再 unscale 还原;动态 loss scaling 会自动调整该系数。
fp16 vs bf16
bf16 指数位与 fp32 相同、动态范围大,通常无需 loss scaling、更稳定,但尾数精度低;fp16 精度高但范围窄,需缩放。新硬件多优先 bf16。
收益与代价
收益:训练更快、显存更省、可上更大 batch/模型。代价:需注意数值稳定(如 softmax、norm 仍用 fp32),裁剪要在 unscale 后做。PyTorch autocast + GradScaler、DeepSpeed 均原生支持。
常见误区
⚠️ 常见踩坑
不是把所有运算都转 fp16——归一化、softmax、loss 等数值敏感算子仍保留 fp32;bf16 范围大但尾数精度低于 fp16,不等于"全面更好"。
追问
追问 1:为什么必须保留一份 fp32 的主权重?
参数更新量(learning_rate × 梯度)常远小于权重本身,在 fp16 下与权重相加会因有效位数不足被舍入丢弃,导致更新失效。fp32 master weights 累积这些微小更新,再拷回 fp16 用于下一步计算。
追问 2:loss scaling 的系数过大或过小会怎样?
过小则小梯度仍下溢丢失;过大则梯度可能上溢成 inf/NaN。动态 loss scaling 会在出现 inf/NaN 时跳过该步并调小系数,连续若干步正常则尝试调大,自动维持在安全区间。
延伸学习
与本题相关的知识库文章、术语、工具与行业资讯。
🛠️ AI 工具