在 15.3 节中我们提到,Tensor Core 对矩阵乘加(GEMM)做了硬件级加速;在 15.5 节中我们又看到,HBM 显存的物理带宽始终赶不上计算单元的数据胃口。计算精度正是连接这两者的核心杠杆:降低精度,意味着同样的显存带宽能吞吐更多数据,同样的 Tensor Core 能在单位时间内完成更多次乘加运算,同时也意味着模型权重占用的显存直接减半甚至缩到四分之一。但代价是什么?数值表示范围的收窄和精度的损失,可能导致训练发散或推理质量下降。
本节把大模型场景下最常用的五种精度格式放到一起对比,帮你在“算得快、装得下”与“算得准”之间做出不踩坑的选择。
一、浮点数的物理本质:符号、指数与尾数
要理解不同精度的差异,必须先拆解浮点数的二进制构成:
- 符号位(Sign):正负号;
- 指数位(Exponent):表示数值的动态范围(能表示多大或多小的数);
- 尾数位(Mantissa/Significand):表示有效数字的精度(小数点后多细)。
FP32 采用 1-8-23 分布(1 位符号、8 位指数、23 位尾数),而 FP16 和 BF16 都是 16 位,但切法不同,这直接导致了它们截然不同的性格。
二、五种精度的“身份证”与能力画像
| 格式 | 总位数 | 指数位 | 尾数位 | 动态范围 | 有效精度 | 大模型典型场景 |
|------|--------|--------|--------|----------|----------|----------------|
| FP32 | 32 | 8 | 23 | 极大(≈1.0×10⁻¹²⁸ ~ 3.4×10³⁸) | 高(约 7 位十进制) | 参数初始化、主权重备份、梯度累积、科学计算基线 |
| FP16 | 16 | 5 | 10 | 较小(≈6.1×10⁻⁵ ~ 6.5×10⁴) | 中(约 3.3 位十进制) | 混合精度训练(配合 Loss Scaling)、推理 |
| BF16 | 16 | 8 | 7 | 大(与 FP32 相同) | 较低(约 2.3 位十进制) | 大模型训练首选(A100/H100 原生支持) |
| INT8 | 8 | — | — | 依赖量化缩放因子 | 低 | 推理量化(W8A8/W8A16)、高并发服务 |
| INT4 | 4 | — | — | 极有限 | 极低 | 极限压缩、端侧/消费级显卡部署、长上下文显存急救 |
三、训练场景:BF16 为什么几乎统一了江湖
FP16 的隐痛:FP16 的指数位只有 5 位,动态范围非常窄。大模型训练时,梯度更新往往分布在极小的数值区间,FP16 很容易发生下溢(Underflow,梯度变成 0)或上溢(Overflow,Loss 变成 NaN)。为了缓解这个问题,NVIDIA 在 Volta 架构时代引入了混合精度训练 + Loss Scaling(损失缩放)——前向反向用 FP16 加速,但维护一份 FP32 的主权重(Master Weights),并把损失乘以一个系数来保住小梯度。这能跑通,但增加了工程复杂度。
BF16 的破局:BF16(Brain Floating Point)把 FP32 的 8 位指数直接拿过来,只砍尾数到 7 位。这意味着它的动态范围与 FP32 完全一致,几乎不需要 Loss Scaling,却能享受和 FP16 同等的 Tensor Core 吞吐带宽。从 A100(Ampere)开始,NVIDIA Tensor Core 原生支持 BF16,使其成为今天千亿模型预训练的事实标准。
TF32(补充):A100 还引入了 TF32(1-8-10,共 19 位),它在矩阵乘法内部自动使用,对外暴露为 FP32 接口。对开发者而言,开启 TF32 几乎是零成本提速 8 倍(相比 FP32)的隐藏开关,但只影响 GEMM 运算。
实用结论:如果你用 A100/H100/H800 做预训练或全参数微调,直接开 BF16;如果是 V100 或更老的卡,只能退回到 FP16 + Loss Scaling;如果数值极其敏感(某些强化学习奖励模型训练),关键步骤可局部回退 FP32。
四、推理场景:INT8 与 INT4 的量化实践
训练结束后进入部署阶段,精度选择逻辑完全不同:此时权重已经收敛,不再需要反向传播,目标变成降低单请求显存占用和提升并发吞吐。
INT8:成熟的高性能甜点
- 原理:将浮点权重映射到 [-128, 127] 的整数区间,需要一个缩放因子(Scale)和零点(Zero-point)。
- 做法:PTQ(训练后量化)最为常见,用几百条校准数据确定最优缩放参数即可。
- 收益:权重体积减半,Tensor Core 的 INT8 峰值算力通常是 FP16 的 2 倍,同时显存带宽压力减半。
- 代价:在大多数大模型上,INT8 的困惑度(Perplexity)损失极小,人类几乎无法感知;但在需要精确数值计算(如数学推理、代码生成)的任务上,可能出现可测量的掉点。
INT4:极限压缩的双刃剑
- 原理:每个权重只占 4 个 bit,16 个权重打包进一个 INT64。
- 主流方案:GPTQ(逐层量化)、AWQ(保护重要权重通道)、GGUF/GGML(CPU+GPU 混合卸载)。
- 收益:70B 参数的 FP16 模型需要约 140 GB 显存,INT4 量化后可压到约 40–45 GB,配合 24 GB 显存的 RTX 4090 甚至能跑起来(配合 CPU 卸载或分层加载)。
- 代价:尾数被砍到几乎只剩“方向”信息,长上下文推理、复杂逻辑链条、少样本学习(Few-shot)等任务的质量衰减明显;且 INT4 的解量化开销在某些场景下会吃掉部分算力收益。
实用结论:在线 API 服务追求成本与效果平衡,首选 INT8(或 FP16 保效果);个人本地部署、端侧运行或显存实在不够时,才考虑 INT4,并优先选用 AWQ/GPTQ 等保护敏感通道的算法,而非粗暴的线性量化。
五、性能与显存的真实换算关系
不要只看理论峰值,要看大模型实际工作流中的收益:
| 对比项 | FP32 | FP16/BF16 | INT8 | INT4 |
|--------|------|-----------|------|------|
| 权重显存占用 | 基准(2×) | 1× | 0.5× | 0.25× |
| KV-Cache 占用 | 2× | 1× | 可量化至 0.5× | 较少用 |
| Tensor Core 峰值算力 | 1× | 2×(同代显卡) | 4× | 8×(理论) |
| 实际推理加速比 | 1× | 1.5–2× | 2–3× | 2–4×(受带宽瓶颈限制) |
| 训练稳定性 | 最稳定 | 需 Loss Scaling(FP16) | 不适用 | 不适用 |
| 效果损失 | 无 | 几乎无损 | 极小 | 可感知 |
关键洞察:大模型推理的瓶颈往往不在算力,而在显存带宽(15.5 节所述 HBM 带宽)。INT8/INT4 把数据量砍半或砍到四分之一,直接缓解了带宽压力,所以即使 Tensor Core 没跑满,整体吞吐也会显著提升。但对于计算密集型的预训练,BF16 的 2× 算力优势是实打实的。
六、选型决策树(工程师版)
- 预训练 / 全参数微调:BF16 + FP32 主权重(混合精度)。如果你有 A100/H100,开
torch.bfloat16;如果是 V100,用torch.float16+GradScaler。 - SFT / RLHF 对齐训练:与预训练相同,优先 BF16;若奖励模型训练出现数值不稳定,可尝试把奖励模型的最后几层或 Loss 计算保留 FP32。
- 生产环境推理(效果优先):FP16。这是目前开源模型(Llama、Qwen、Mistral)发布时的默认精度,未经充分验证不要轻易量化。
- 生产环境推理(成本/并发优先):INT8(W8A8 或 W8A16)。使用 TensorRT-LLM、vLLM 或昇腾 CANN 的量化工具链,配合校准数据集上线。
- 消费级显卡 / 本地部署 / 长上下文急救:INT4(AWQ/GPTQ)。适合个人开发者、边缘设备或需要把 70B 模型塞进单张 24GB/48GB 显存的场景,但要接受复杂推理任务的轻微降智。
- 绝对不要做的事:用 FP32 做全量推理部署(除非你在搞科研对标)——同样的卡,FP32 只能跑一半的 batch size,延迟和成本都是 FP16 的两倍。
七、一个常见误区:精度越低,一定越快?
不一定。INT4 的理论峰值算力是 FP16 的 4 倍,但在解码阶段(Decoding),大模型是逐 Token 生成的,矩阵尺寸小,严重受限于显存带宽和启动开销(Kernel Launch)。此时 INT4 的解量化(Dequantization)和打包/拆包开销可能吃掉收益。另外,激活值(Activation)量化比权重量化困难得多——只做权重量化(W4A16)能省显存,但计算时仍需反量化为 FP16,速度提升有限;只有权重和激活同时量化(W8A8)才能把 Tensor Core 的 INT 管线真正跑满。
在下一章(第 16 章)中,我们将把这些精度工具放回大模型的完整硬件图景里:训练时的瓶颈究竟是算力、显存还是通信?推理时为什么 batch size 和序列长度会改变你的精度选择?以及国产 GPU 在 FP16/BF16/INT8 管线上的适配现状如何。