LLMs 浮点数
一、fp32 和 fp16 的区别,混合精度的原理
1. fp32 与 fp16 的对比
特性 | fp32(单精度) | fp16(半精度) |
---|
位数 | 32 位(4 字节) | 16 位(2 字节) |
内存占用 | 高 | 低(仅为 fp32 的 50%) |
数值范围 | 约 ±3.4×10³⁸ | 约 ±6.5×10⁴ |
精度(尾数) | 23 位(约 7 位有效十进制数) | 10 位(约 3 位有效十进制数) |
用途 | 高精度计算(如梯度更新) | 高效计算(如矩阵乘法) |
2. 混合精度训练的原理
- 核心思想:结合 fp16 的高效性和 fp32 的稳定性,在训练中动态切换精度。
- 实现方式:
- 前向传播与反向传播:使用 fp16 加速计算,减少显存占用。
- 权重更新:保留 fp32 的主权重副本,避免梯度下溢/溢出。
- 损失缩放(Loss Scaling):放大 fp16 的梯度值,防止因精度丢失导致的梯度归零。
- 支持框架:
- PyTorch(
torch.cuda.amp
自动混合精度模块)。 - TensorFlow(
tf.keras.mixed_precision
)。
二、半精度(fp16)是什么?
1. 定义
- 半精度浮点数(fp16)是一种 16 位的二进制浮点格式,遵循 IEEE 754 标准,用于平衡计算效率与数值精度。
- 应用场景:
- 深度学习模型训练与推理(如 LLMs、CV 模型)。
- 移动端/边缘设备部署(减少内存与算力需求)。
2. 优缺点
优点 | 缺点 |
---|
显存占用减少 50% | 数值范围窄,易溢出/下溢 |
计算速度提升 20%-50% | 精度损失可能影响模型收敛 |
支持硬件加速(如 NVIDIA Tensor Core) | 需结合混合精度优化稳定性 |
三、半精度的理论原理
1. 位分配
- 符号位(1 位):表示正负(0 正,1 负)。
- 指数位(5 位):偏移值为 15,实际指数范围为 [-14, 15]。
- 尾数位(10 位):隐含前导位为 1,实际精度为 11 位二进制数。
2. 数值表示公式
[
\text{Value} = (-1)^{\text{符号位}} \times 2^{\text{指数}-15} \times \left(1 + \sum_{i=1}^{10} \text{尾数}_i \times 2^{-i}\right)
]
3. 与 fp32 的对比
参数 | fp16 | fp32 |
---|
指数范围 | [-14, 15] | [-126, 127] |
最大数值 | 65,504 | 3.4×10³⁸ |
最小数值 | 6.1×10⁻⁵(非规约) | 1.2×10⁻³⁸ |
四、半精度在 LLMs 中的应用
1. 训练加速
- 显存优化:半精度可将模型显存占用减半,支持更大批次(Batch Size)。
- 计算效率:NVIDIA GPU 的 Tensor Core 对 fp16 有硬件加速,吞吐量提升显著。
2. 常见问题与解决方案
- 梯度下溢:通过损失缩放(Loss Scaling)放大梯度值。
- 数值溢出:使用混合精度保留 fp32 主权重,定期同步精度。
3. 实际案例
- GPT-3:使用 fp16 训练,显存需求从 320GB 降至 160GB。
- BERT-Large:混合精度训练速度提升 2-3 倍。
五、扩展阅读
- IEEE 754 标准:定义浮点数的二进制格式与运算规则。
- BFloat16(bfloat16):另一种 16 位格式,保留 fp32 的指数位,更适合深度学习。