这是「LLM 训练与推理优化系列」第 1 篇。系列共 5 篇,按 基础 → 推理 → 量化 → 训练理论 → 训练工程 的顺序展开。本篇先把后面 4 篇都会用到的概念统一一遍:字节、精度、训练四件套、推理三件套。
0. 为什么是显存
当模型或上下文接近单卡容量上限时,显存(HBM) 往往是先触发 OOM 的硬约束;在小模型、低并发或计算密集型任务中,算力、带宽和延迟也可能先成为瓶颈。本文只讨论显存账本。
所以在 LLM 工程里,「这台机器能不能跑这个模型?」「能跑多长上下文?」「能开多大 batch?」可以先用显存账本排除不可能的组合,再结合吞吐和延迟实测判断。
而这个账本的最小单位,是 bit。
1. bit 与 byte
计算机的最小信息单位是 bit,只有 0 和 1 两种状态。8 个 bit 凑成 1 个 byte:
n 个 bit 能表示 种状态。这是后面所有精度推导的基石:
| 位宽 | 状态数 | 无符号范围 | 有符号范围(补码) |
|---|---|---|---|
| 1 bit | 2 | 0 ~ 1 | -1 ~ 0 |
| 4 bit | 16 | 0 ~ 15 | -8 ~ 7 |
| 8 bit | 256 | 0 ~ 255 | -128 ~ 127 |
| 16 bit | 65536 | 0 ~ 65535 | -32768 ~ 32767 |
本文同时使用两套容量单位,并始终写清楚:
-
1 KB = bytes
-
1 MB = bytes
-
1 GB = bytes
-
1 KiB = bytes
-
1 MiB = bytes
-
1 GiB = bytes
厂商容量通常标为 GB;操作系统、框架日志和工具也可能显示 GiB/MiB。两者不能直接混写:。后文的十进制模型大小采用 GB,二进制内存页大小采用 KiB/GiB。
2. 浮点精度全谱
LLM 里的参数、梯度、激活值绝大多数都是浮点数。浮点数的二进制表示是科学计数法:
它由三部分组成:符号位 / 指数位 / 尾数位。指数位决定动态范围(能表示多大的数),尾数位决定精度(同一个数量级里有多细)。这两者怎么分配,定义了不同的浮点格式。
2.1 高精度阵营:FP32 / FP16 / BF16
| 格式 | 总 bit | 符号 | 指数 | 尾数 | 字节 | 数值范围 | 备注 |
|---|---|---|---|---|---|---|---|
| FP32 | 32 | 1 | 8 | 23 | 4 | IEEE 754,深度学习的”金标准” | |
| FP16 | 16 | 1 | 5 | 10 | 2 | 范围较窄,常需 loss scaling;仍被部分硬件和训练栈使用 | |
| BF16 | 16 | 1 | 8 | 7 | 2 | 范围与 FP32 一致,精度低 |
BF16 保留 FP32 的 8 位指数,把尾数缩至 7 位。相较 FP16,它的指数范围可降低因指数范围不足导致的溢出/下溢风险;代价是有效精度更低。是否优于 FP16 仍取决于硬件、算子、loss scaling 策略和训练稳定性验证。
2.2 低精度新贵:FP8(E4M3 / E5M2)
H100 / B200 等新一代 GPU 原生支持 FP8。它有两种变体:
| 变体 | 符号 | 指数 | 尾数 | 数值范围 | 主要用途 |
|---|---|---|---|---|---|
| E4M3 | 1 | 4 | 3 | 常用于偏精度的前向张量,取决于 recipe | |
| E5M2 | 1 | 5 | 2 | 常用于偏范围的梯度张量,取决于 recipe |
FP8 训练通常会在前向和反向为张量选择 E4M3 或 E5M2;常见配法是前向张量偏向 E4M3、梯度偏向 E5M2,但具体取决于 recipe 和硬件实现。FP8 不是把 BF16 直接强转即可:NVIDIA Transformer Engine 的 current/delayed scaling 都为每个量化张量维护 FP32 scale,并根据当前或历史 amax 更新;超出表示范围的值会被裁剪。
2.3 整数精度:INT8 / INT4
整数没有指数/尾数之分,n bit 直接对应 个量化级别:
| 格式 | 字节 | 有符号范围 | 主要用途 |
|---|---|---|---|
| INT8 | 1 | -128 ~ 127 | 推理量化(GPTQ/AWQ INT8) |
| INT4 | 0.5 | -8 ~ 7 | 推理极致压缩(GPTQ/AWQ INT4) |
INT4 一个数只占半个字节,两个 INT4 数打包进一个 byte。怎么把 BF16 的浮点权重压成 INT4 而不损失太多精度?这是 第 3 篇 要回答的问题。
2.4 一张表对比
| 格式 | 字节 | 动态范围 | 精度 | 适合 |
|---|---|---|---|---|
| FP32 | 4 | 极大 | 极高 | 优化器 master copy / Adam 状态 |
| BF16 | 2 | 极大 | 中等 | 训练前向/反向、推理 |
| FP16 | 2 | 中 | 中高 | 训练/推理;常与 loss scaling 配合 |
| FP8 | 1 | 较大(E5M2)/ 中(E4M3) | 较低 | H100+ 训练 / 推理 |
| INT8 | 1 | — | 离散 256 级 | 推理量化 |
| INT4 | 0.5 | — | 离散 16 级 | 推理极致量化 |
在支持 BF16 的硬件上,它是 LLM 训练常见的计算精度;FP32 也可能用于累积、归约或数值敏感算子。FP8、INT8、INT4 的可用性、精度与内核支持取决于训练或推理栈,不能仅按位宽判断。
3. 快速心算:参数量 → 显存
知道每个参数占几字节,就能秒算模型权重的显存:
以标称 7B( 参数)模型为例:
| 精度 | 字节/参数 | 7B 模型权重 |
|---|---|---|
| FP32 | 4 | 28 GB |
| BF16 | 2 | 14 GB |
| FP8 | 1 | 7 GB |
| INT8 | 1 | 7 GB |
| INT4 | 0.5 | 3.5 GB |
标称 70B 模型按同一口径约为 10 倍:BF16 = 140 GB,INT4 的裸权重 = 35 GB。后者不含 group scale、zero-point、打包对齐和运行时工作区,实际 checkpoint 与显存占用会更大。
但这只是「冰山一角」。真正的显存大头在哪,要看是 训练 还是 推理——这两类场景的显存组成结构完全不同。
4. 训练 vs 推理:显存全景对比
这是本篇最重要的一节。后面 4 篇都会回到这张图。
4.1 推理三件套
推理时,模型只做前向传播,显存被三类东西吃掉:
| 组件 | 含义 | 是否常驻 |
|---|---|---|
| 模型参数 | 加载后不变 | 是 |
| KV Cache | 自注意力缓存历史 token 的 K、V | 是(生成一个 token 就 append 一份) |
| 临时工作区 | 前向中间张量、attention/采样等 kernel 缓冲 | 否(峰值随引擎与请求变化) |
公式骨架:
其中 是序列长度, 是 batch size。KV Cache 与 线性增长,可精确核算;临时工作区取决于 prefill/decode、并发和 kernel,需在目标引擎测量。第 2 篇 会展开这两类账。
4.2 训练四件套(混合精度)
训练时,除了前向还要做反向 + 优化器更新。在主流的 BF16 混合精度训练下,每个参数在 GPU 里有这么几份”分身”:
| 组件 | 精度 | 字节/参数 | 用途 |
|---|---|---|---|
| 模型参数 | BF16 | 2 | 前向 + 反向计算用 |
| 梯度 | BF16 | 2 | 反向产生,更新时消费 |
| FP32 master copy | FP32 | 4 | 真正被优化器更新的权重 |
| Adam momentum | FP32 | 4 | 一阶矩估计 |
| Adam variance | FP32 | 4 | 二阶矩估计 |
| 合计 | 16 | 一种常见 Adam 混合精度配方的模型状态 |
这里 表示参数数量(个),系数 16 表示每个参数 16 字节的 模型状态(不含激活)。它的前提是:BF16 参数和梯度各一份、独立 FP32 master copy 一份、以及 FP32 Adam 两份。它不是所有训练都必须具备的固定账单;优化器、状态精度、参数副本、冻结参数与分片策略都会改变它。
本系列约定: 永远表示参数数量(无单位的”个数”), 中的系数 单位是字节/参数。这样讲 、 这类公式时不会混淆。
4.3 为什么常用 FP32 保存 Adam 状态?
经常被问的问题:BF16 都能训前向,为什么 Adam 的 、 常保存为 FP32?
Adam 更新公式(简化):
注意 ,,每一步加进来的”小增量”非常小。在百万步训练里这些小增量持续累积,FP16 / BF16 的尾数位(10 / 7 bit)在小数动态范围下精度不足,会出现:
- 大的 加上小的新梯度 → 新梯度被舍入掉,相当于没加
- 小梯度自身被舍入到 0
这种”看不见的损失”会增加不稳定或漂移的风险。FP32 的 23 位尾数通常能更稳妥地保留这些增量,因此是常见默认选择;也存在 8-bit Adam、BF16 state 或无 master copy 等替代方案,需以收敛验证换取显存。
同理,许多混合精度实现让 optimizer 更新 FP32 master copy,再把它转换为 BF16 供计算使用;是否保留这份副本由实现和数值稳定性要求决定,并非 BF16 训练的定义性要求。
4.4 一目了然的对比
7B 模型在两种场景下的显存最低需求(不计激活、不算 batch):
| 场景 | 显存账本 | 7B 总额 |
|---|---|---|
| 推理(BF16) | 模型权重 = | 14 GB |
| 训练(表中这类 BF16 + FP32 Adam 状态) | 全套模型状态 = | 112 GB |
这里的 只比较这套训练模型状态与 BF16 裸权重;它不包含训练激活、临时工作区、通信 bucket,也不包含推理 KV Cache 和工作区。使用 ZeRO、offload、低精度优化器或 PEFT 后比例也会改变,因此不能把“训练必为推理 8 倍”当作部署结论。
若再算上激活值和 KV Cache,差距会随序列长度、batch 和实现改变;每次都应按实际配置重算账本。
5. 优化技术地图
显存账本拆完,优化的方向也就清楚了。每一项开销都有针对性的工具,分属本系列后续的 4 篇:
显存优化全景├─ 推理优化│ ├─ 模型参数 → 量化(INT4/INT8/FP8) ─→ 第 2、3 篇│ ├─ KV Cache → GQA/MQA、KV 量化、PagedAttention ─→ 第 2 篇│ └─ 注意力工作区 → FlashAttention ─→ 第 2 篇│└─ 训练优化 ├─ 模型状态冗余(多卡 DDP)→ ZeRO-1/2/3 ─→ 第 4 篇 ├─ 单机显存上限 → ZeRO-Offload / Infinity ─→ 第 4 篇 ├─ 通信瓶颈 → ZeRO++、混合并行 ─→ 第 4 篇 └─ 工程层 ├─ 数据填充浪费 → Packing / Padding-Free ─→ 第 5 篇 ├─ 大词表 logits → Chunked Cross-Entropy ─→ 第 5 篇 ├─ 全参更新成本 → PEFT (LoRA/QLoRA) ─→ 第 5 篇 ├─ 中间激活峰值 → Gradient Checkpointing ─→ 第 5 篇 └─ Kernel 效率 → Liger Kernel ─→ 第 5 篇每条线索都会在后续篇章里展开数学和代码。
6. 系列 roadmap
| # | 主题 | 你将学到 |
|---|---|---|
| 1 | 显存基础(本篇) | bit/byte、精度、训练 vs 推理全景 |
| 2 | 推理显存拆解与优化 | KV Cache 公式、Flash Attention、PagedAttention |
| 3 | 量化深入 | 对称/非对称、GPTQ、AWQ |
| 4 | 训练显存与 ZeRO | 16Ψ 推导、ZeRO-1/2/3、FSDP |
| 5 | SFT 训练实战 | TRL Packing、Liger、Chunked NLL、LoRA |
7. 小结
- bit → byte → 精度 → 显存,链条很短,但每一步都决定大模型能不能跑得起来。
- BF16、FP32、FP8/INT4 的选择取决于硬件、内核与数值验证,不能只看位宽。
- 先分开列出模型状态、激活和工作区,再按具体训练或推理配置估算;不要用一个固定倍率替代账本。
- = 参数数量; 仅是上述 Adam 混合精度配方下的 16 字节/参数模型状态。
下一篇 → LLM 训练与推理优化(二)— 推理显存拆解与优化,从 Llama-3-8B 的实例出发,把推理三件套的每一笔账算清楚。
参考资料
- NVIDIA. Hopper Architecture In-Depth (FP8 / TF32 details). 2022.
- Micikevicius et al. FP8 Formats for Deep Learning. NVIDIA / Arm / Intel, 2022. arXiv:2209.05433; Transformer Engine FP8 scaling
- IEEE 754-2019. IEEE Standard for Floating-Point Arithmetic.
- Kalamkar et al. A Study of BFLOAT16 for Deep Learning Training. 2019. arXiv:1905.12322
- Rajbhandari et al. ZeRO: Memory Optimizations Toward Training Trillion Parameter Models. SC ‘20. arXiv:1910.02054 — 16Ψ 公式来源