1. 混合精度训练概述

什么是混合精度训练

混合精度训练,说白了就是让模型在训练时同时使用 FP16 和 FP32 两种精度。

你可能会问:为什么不干脆全用 FP16?或者全用 FP32?

嗯,这里有个关键点。FP32 精度高但占显存,FP16 省显存但容易溢出。混合精度训练就是取两者的长处——大部分计算用 FP16 加速,关键地方用 FP32 保精度。

我刚开始接触这个概念时,也觉得挺绕的。后来在实际项目中跑了一遍,才真正理解它的价值。

核心思想:用 FP16 做矩阵乘法等计算密集型操作,用 FP32 维护权重和梯度等精度敏感数据。

为什么需要混合精度训练

原因其实很直接——模型越来越大,显存越来越不够用。

我记得几年前训练 BERT-Large 时,单卡 32G 显存都捉襟见肘。现在动不动就是百亿参数模型,纯 FP32 训练?想都别想。

具体来说,混合精度训练解决了三个痛点:

  • 显存减半:FP16 只占 2 字节,FP32 占 4 字节。光权重和激活值就能省一半空间
  • 训练加速:现代 GPU 对 FP16 有专门的 Tensor Core,吞吐量是 FP32 的 2-8 倍
  • 通信开销降低:多卡训练时,梯度同步的数据量直接减半

我在项目中遇到过最极端的情况——一个 7B 参数的模型,纯 FP32 需要 4 张 A100 才能跑起来。换成混合精度后,2 张卡就搞定了,训练速度还快了 40%。

个人经验:如果你的模型显存占用超过 70%,混合精度训练几乎是必选项。别犹豫,直接上。

FP16 与 FP32 的对比

先看一张对比表,一目了然:

特性 FP32 FP16
位宽 32 位 16 位
指数位 8 位 5 位
尾数位 23 位 10 位
表示范围 ~3.4×10³⁸ ~6.5×10⁴
最小正数 ~1.4×10⁻⁴⁵ ~5.9×10⁻⁸
显存占用 4 字节 2 字节
典型吞吐 1x (基准) 2-8x

看到 FP16 的表示范围了吗?只有 6.5×10⁴。这意味着什么?

举个例子。你算出来的梯度是 0.00001,FP16 直接给你变成 0。这就是所谓的「下溢出」问题。

反过来,如果梯度大于 65504,FP16 就变成无穷大——「上溢出」。

我曾经调试过一个模型,loss 死活不降。查了两天才发现,是梯度在 FP16 下全被截断了。嗯,那之后我就再也不敢忽视精度问题了。

避坑指南:FP16 的「精度黑洞」在 0 附近。如果你的模型有大量接近零的梯度或激活值,一定要配合 loss scaling 使用。

混合精度训练的发展历史

说起来,混合精度训练并不是什么新鲜事。我简单梳理一下关键节点:

  • 2017 年:NVIDIA 在 Volta 架构中引入 Tensor Core,首次为 FP16 计算提供硬件加速
  • 2018 年:百度发表《Mixed Precision Training》论文,提出完整的混合精度训练框架
  • 2019 年:PyTorch 1.5 正式支持自动混合精度(AMP),NVIDIA 推出 APEX 库
  • 2020 年:TensorFlow 2.4 原生支持混合精度训练,AMP 成为标配
  • 2021 年至今:BF16、TF32 等新格式出现,混合精度训练进入百花齐放阶段

我个人印象最深的是 2019 年。那时候 PyTorch 的 AMP 刚出来,我第一时间就试了。说实话,第一次跑通时还挺激动的——同样的代码,加两行就提速 50%,这种好事不多见。

现在回头看,混合精度训练已经成了深度学习的基础设施。就像当年从 CPU 训练转向 GPU 训练一样,回不去了。

混合精度训练核心知识体系 混合精度训练 FP16 计算 矩阵乘法 卷积运算 FP32 维护 权重更新 Loss Scaling 关键技巧:梯度缩放 + 精度回退 FP16 做计算加速,FP32 保精度稳定,两者配合达到最佳效果

这张图把混合精度训练的核心逻辑串起来了。左边是 FP16 负责的加速部分,右边是 FP32 负责的精度维护,中间通过梯度缩放和精度回退来衔接。

我个人觉得,理解这张图比背一堆参数重要得多。你想想看,只要把握住「计算用 FP16,存储用 FP32」这个原则,后面那些细节都是水到渠成的事。

一句话总结:混合精度训练不是非此即彼的选择题,而是「既要又要」的工程艺术。