dtype
浮点数
计算机里的浮点数由三部分组成:符号位 (Sign) + 指数位 (Exponent) + 尾数位/精度位 (Mantissa/Fraction)。
- 符号位:决定正负。
- 指数位:决定数值的范围(能表示多大的数,多小的数)。
- 尾数位:决定数值的精度(小数点后能精确到几位)。
各个数据类型的数值位含义:
| 格式 | 总位数 | 符号位 (Sign) | 指数位 (Exponent) [范围] | 尾数位 (Mantissa) [精度] |
|---|---|---|---|---|
| FP32 (标准) | 32 | 1 | 8 | 23 |
| FP16 (传统) | 16 | 1 | 5 (范围窄) | 10 (精度尚可) |
| BF16 (新贵) | 16 | 1 | 8 (范围同FP32) | 7 (精度低) |
- FP16 说:“我想要保留多一点细节(精度),所以我牺牲了指数位。”
- BF16 说:“我不想管溢出的问题,我要和 FP32 一样的范围,所以我牺牲了细节(精度)。”
深入理解 FP16 (IEEE 754 Half-Precision)
特点:精细但“腿短”
- 优势:它的精度相对较高(有10位尾数)。在处理需要细微差别的计算(如某些图像处理任务或早期深度学习模型)时,数值更准确。
- 致命弱点:范围太小。
- 它的指数位只有 5 位,最大只能表示约 $65504$。
- 在深度学习训练中,梯度的变化范围非常大。如果不小心,数值很容易变成
NaN(溢出) 或0(下溢)。
- 补救措施:为了用 FP16 训练,必须使用一种叫 “混合精度训练 (Mixed Precision) + Loss Scaling” 的技术。你需要人为地把数值放大(Scaling),防止它因为太小变成0,算完后再缩回去。这增加了软件开发的复杂性。
深入理解 BF16 (Brain Floating Point)
特点:粗糙但“腿长”
- 起源:Google Brain 团队为了 TPU 设计的格式(所以叫 Brain Float)。
- 核心逻辑:它是直接把 32 位的 FP32 截断成 16 位。它保留了 FP32 完整的 8 位指数,直接砍掉了后面的尾数。
- 优势:
- 范围宽:它能表示的数值范围和 FP32 一模一样。你几乎不需要担心数值溢出(Overflow)或下溢。
- 易于转换:从 FP32 转 BF16 不需要复杂的数学运算,直接扔掉后 16 位就行,硬件实现非常简单且快。
- 训练稳定:在训练大模型(如 Transformer/LLM)时,无需复杂的 Loss Scaling 技巧,开箱即用。
- 弱点:精度低。它的有效数字位数较少。但令人惊讶的是,深度神经网络(尤其是大模型)对精度的容忍度很高,它们更像是一种统计模型,一点点噪音(低精度)通常不会影响最终效果,甚至有时能起正则化作用。
支持情况
硬件支持:
- 早期的 GPU(如 NVIDIA Pascal/Volta V100)主要支持 FP16。
- 现代 GPU(如 NVIDIA Ampere A100, Hopper H100, RTX 30/40系列)和 TPU 都原生支持 BF16。