符号、指数、尾数
IEEE 754 浮点数格式
每个浮点数存储三个字段:
- 符号位 (1 位): 正或负
- 指数 (E 位): 幅度尺度,2 的整数幂
- 尾数 (M 位): 小数精度,介于 1.0 与 ~2.0 之间的数
总位数 = 1 + E + M。值大致等于 (-1)^sign (1 + mantissa) 2^(exponent - bias)。
训练中两个属性很重要:
动态范围 = 2^(2^E)(大致)。更多的指数位意味着可以表示更小和更大的数,而不会溢出。
精度 = 每个 2 的幂有 2^M 个不同值。更多的尾数位意味着在连续的 2 的幂之间具有更精细的表示。
三种格式
| 格式 | 总位数 | 符号 | 指数 | 尾数 | 动态范围 | 精度 |
|---|---|---|---|---|---|---|
| FP32 | 32 | 1 | 8 | 23 | ~10^-38 到 ~10^38 | ~7 位数字 |
| FP16 | 16 | 1 | 5 | 10 | ~10^-5 到 ~10^5 | ~3 位数 |
| FP8 E4M3 | 8 | 1 | 4 | 3 | ~2^-9 到 ~448 | ~2 位数 |
FP8 E4M3 表示“4 个指数位,3 个尾数位”。另一种 FP8 E5M2 格式以精度换取范围;ANDREA 实验使用 E4M3,因为 Transformer 激活值保持在狭窄的幅度范围内,额外精度胜过额外范围。
每参数字节数
为什么低精度运行更快
内存带宽主导训练速度
现代 GPU 花费更多时间等待内存而非计算。RTX 4090 具有 1008 GB/s 内存带宽和 165 TFLOPS 的 FP16 计算能力。一个典型的层从 VRAM 读取权重,乘以激活值,然后将结果写回。带宽而非计算决定吞吐量。
将精度减半会将每个参数的字节数减半,因此读取相同权重只需一半的内存带宽。吞吐量大致翻倍。
张量核心:硬件加速矩阵乘法
RTX 4090 搭载专用的张量核心单元,能够直接以 FP16 或 FP8 计算矩阵乘法。单个张量核心操作可在一个周期内乘以一个小块(例如 16x16),比标量 FP32 乘法快得多。
来自 ANDREA-120M 的实证数据:
| 精度 | 步数/分钟 | 备注 |
|---|---|---|
| FP32 | ~3 | 基线;无张量核心加速 |
| FP16 | ~6 | cuBLAS 张量核心;2x 加速 |
| FP8 E4M3 | ~6 | 张量核心;与 FP16 相当 |
FP8 在此工作负载上未能在吞吐量上击败 FP16,因为计算吞吐量不再是瓶颈;内存带宽和启动开销成为限制因素。ANDREA-120M v3 以 FP16 cuBLAS 在 6 步/分钟的速度发货,以提供舒适的安全裕度而不损失吞吐量。
FP8 下的 NaN 风险
FP8 E4M3 表示从 ~2^-9 到 ~448 的数字。超出该范围的激活或梯度会溢出为 NaN(不是数字)或下溢为零。单个 NaN 会毒化所有下游计算:包含 NaN 的矩阵乘法返回全 NaN;全 NaN 梯度会破坏 AdamW 状态;带有 NaN m 和 v 的 AdamW 输出 NaN 更新;权重变为 NaN;整个训练运行崩溃。
ANDREA 的 FP8 实验偶尔产生 NaN 悬崖,需要损失缩放、计划精度切换或回退路径。FP16 动态范围(~10^-5 到 ~10^5)足够宽,NaN 事件保持罕见,无需复杂的缩放技巧。
为新运行选择精度
在单个 4090 上拟合 120M
引言课中的 6-8 倍乘数
回想 grow_a_language_model_intro,训练内存大约等于原始权重数量的 6-8 倍,包括:
- 权重 (1x)
- Adam 一阶矩 m (1x)
- Adam 二阶矩 v (1x)
- 梯度缓冲区 (1x)
- 激活值与临时变量 (~2-4x,取决于批次与上下文)
ANDREA-120M 在 FP16 下,batch_size=8, context=1024:
| 组件 | FP16 大小 |
|---|---|
| 权重 | 240 MB |
| m (第一矩) | 240 MB |
| v (第二矩) | 240 MB |
| 梯度 | 240 MB |
| 激活值 | ~2-4 GB (批次, 上下文) |
| 总计 | ~3.5 GB |
RTX 4090 有 24 GB 显存。ANDREA-120M 在 FP16 下使用 ~14%。有充足空间支持更大的批次大小或更长的上下文窗口。ANDREA-12M 总共仅使用 1.4 GB。
混合精度所在的位置
ANDREA 不会 将一切保持在单一精度。混合精度训练存储:
- 主权重: FP32(保持训练稳定性)
- 前向与反向计算: FP16(使用张量核心)
- AdamW 优化器状态: FP32(m 和 v 需要精度以处理长尾更新)
- 梯度缓冲区: FP16(计算侧)
最终内存预算混合了两种。ANDREA的实际占用介于纯FP16(720 MB 优化器状态)与纯FP32(1.44 GB 优化器状态)之间,更接近FP32,因为m和v保持在FP32。
为ANDREA-480M制定预算规模
实践中的精度
相关活动
三个兄弟活动与精度相关:
- 活动 1:入门 / VRAM 预算。 精度会将内存预算算术中的每个项相乘。6-8x 倍数的经验法则无单位;每参数字节数赋予其单位。
- 活动 10: AdamW。 优化器状态(m 和 v)通常保持在 FP32,即使前向/反向计算以 FP16 运行。原因:优化器的长尾累加器精度比运行时速度更重要。
- 活动 12: 梯度裁剪。 裁剪在优化器状态更新前限制梯度幅度。在 FP16 前向/反向和 FP32 优化器的情况下,裁剪发生在精度变化的边界处,也是溢出风险集中的地方。
精度是一个免费的调节旋钮:改变它,模型训练更快且使用更少内存。代价是数值处理:NaN 处理、损失缩放、混合精度纪律。ANDREA-120M v3 展示了回报:120M 参数在消费级硬件上用 23 天训练完成,因为 FP16 将一切减半。