大模型精度、量化与推理速度:从 BF16、INT4 到 TTFT 和 TPS
在同一张 GPU 上,应该部署 32B BF16,还是 70B INT4?为什么量化后显存变小,有时速度也变快,但输出又可能发生变化?要回答这些问题,需要同时理解参数量、数值精度、量化方法和推理瓶颈。
本文从三个角度建立统一认识:
- 权重精度究竟表示什么;
- INT8/INT4 如何从 BF16 模型转换出来;
- 精度、参数量、显存和推理速度如何共同权衡。
显存和 KV Cache 的完整计算可参考上一篇:大模型推理资源估算:权重、KV Cache、显存与部署容量。
一、参数量与参数精度
参数量表示模型中可学习数字的数量:
7B = 70亿个参数
32B = 320亿个参数
70B = 700亿个参数
精度表示每个数字用多少位保存:
| 精度 | 理论位数 | 理论字节/参数 |
|---|---|---|
| FP32 | 32 bit | 4 |
| BF16/FP16 | 16 bit | 2 |
| FP8/INT8 | 8 bit | 1 |
| INT4 | 4 bit | 0.5 |
| INT2 | 2 bit | 0.25 |
降低精度不会减少参数数量。7B INT4 仍然有 70 亿个参数,只是每个参数的表示更紧凑。
基础公式:
[ M_{\text{weights}} \approx P_{\text{total}}\times b_{\text{weight}} ]
例如:
7B BF16 ≈ 14GB
14B INT8 ≈ 14GB
32B INT4 ≈ 16GB(未计量化元数据)
这三种权重大小接近,但模型容量、误差和执行方式完全不同。
二、FP16 与 BF16
浮点数由符号、指数和有效数字组成。
FP16
- 指数位较少;
- 有效数字较多;
- 小数表示较细;
- 动态范围比 BF16 小。
BF16
- 指数范围接近 FP32;
- 有效数字比 FP16 少;
- 动态范围更大;
- 大模型训练和推理通常更稳定。
BF16 和 FP16 都占 2 字节。对大多数推理任务,它们的质量接近原始模型,区别更多体现在硬件支持和数值稳定性。
三、权重、激活和 KV 可以使用不同精度
“一个 INT4 模型”通常只表示权重为 INT4,并不代表所有张量都是 4bit。
例如 W4A16:
Weights:INT4
Activations:BF16/FP16
Accumulation:BF16/FP32
KV Cache:BF16/FP16
常见命名:
W4A16:权重4bit,激活16bit
W8A8: 权重8bit,激活8bit
W8A16:权重8bit,激活16bit
KV Cache 精度也是独立配置。权重 INT4 并不会自动让 KV Cache 变成 INT4。
这四种精度对系统的影响不同:
| 对象 | 主要影响 |
|---|---|
| 权重精度 | 模型显存、权重带宽、模型质量 |
| 激活精度 | 临时显存、矩阵计算速度、数值误差 |
| KV精度 | 长上下文显存和注意力质量 |
| 累加精度 | 数值稳定性 |
四、最基础的量化
以对称 INT8 为例,有符号范围约为:
-127~127
首先计算 Scale:
[ scale=\frac{\max(|w|)}{127} ]
量化:
[ q=\operatorname{round}(w/scale) ]
近似还原:
[ \hat{w}=q\times scale ]
假设原始权重:
[-0.82, -0.31, 0.04, 0.47, 1.26]
量化后可能是:
INT8整数:[-83, -31, 4, 47, 127]
Scale:0.00992
计算时根据 Scale 解释这些整数。模型参数数量没有变化,但权重值变成了近似值。
INT4
INT4 只有 16 个离散等级,所以误差通常比 INT8 大。为降低误差,模型会把矩阵划分成多个 Group:
每32、64或128个权重共享一组Scale
Group 越小:
- 局部拟合更精确;
- Scale 元数据更多;
- 实际字节/参数更大。
因此 INT4 实际占用一般高于理论的 0.5 字节/参数。
五、量化模型是否需要重新训练
绝大多数量化版本不需要重新预训练。主流流程是:
训练一个BF16/FP16基础模型
↓
训练后量化与校准
↓
生成INT8、INT4、GGUF等推理版本
这叫 Post-Training Quantization,简称 PTQ。
校准
校准通常使用几百到几千段代表性文本:
文本前向传播
→ 收集权重和激活分布
→ 找出异常值和敏感通道
→ 确定Scale和裁剪范围
一般不需要标签,也不进行完整预训练。成本通常是几分钟到几小时。
常见方法
GPTQ
逐层或逐块量化,并根据局部误差调整后续权重,减少这一层输出的整体偏差。
AWQ
利用校准激活寻找重要权重通道,对敏感通道进行保护和缩放,再执行低比特量化。
SmoothQuant
主要用于 W8A8。它将部分激活异常值的量化难度转移到权重,使激活分布更平滑。
GGUF
常见于 llama.cpp,提供 Q4、Q5、Q6、Q8 等多种格式,适合 CPU 或 CPU/GPU 混合推理。
QAT
极低比特量化可能需要 Quantization-Aware Training:
已有高精度模型
→ 前向时模拟量化和取整
→ 少量训练让权重适应误差
QAT 通常是短时间微调,不是重新进行完整预训练。
六、量化为什么改变输出
量化会产生:
[ e=\hat{w}-w ]
单个权重误差可能很小,但误差会经过许多层传播,最终改变 Logits。
假设原模型:
首都:9.73
城市:9.68
量化后:
首都:9.66
城市:9.71
最高分 Token 就可能从“首都”变成“城市”。
自回归生成中:
一个Token改变
→ 下一轮输入改变
→ 后续Q/K/V改变
→ 整段文本可能逐渐分叉
所以“输出文本不同”不一定表示量化模型已经完全失效。更可靠的判断方法是比较任务准确率、困惑度、代码通过率和长上下文召回率,而不是要求每次文本逐字相同。
哪些任务更敏感
- 数学和多步推理;
- 复杂代码生成;
- 长上下文检索;
- 小语种;
- 罕见知识;
- Logits 非常接近的选择任务。
一般趋势:
BF16/FP16
→ FP8/INT8
→ 高质量INT4
→ 3bit
→ 2bit
精度越低,质量风险越大,但具体结果高度依赖模型和量化方法。
七、参数量与精度如何平衡
在固定显存中,常见选择是:
小模型 + 高精度
大模型 + 低精度
例如:
7B BF16 ≈ 14GB
14B INT8 ≈ 14GB
32B INT4 ≈ 16GB
在同一模型家族、训练质量和量化质量相近时,更大的高质量 INT4 模型经常可能胜过更小的 BF16 模型,因为参数容量收益可能超过量化误差。
但不能把它当作定律。不同模型还受到:
- 训练数据;
- 架构代际;
- 对齐方法;
- 上下文长度;
- 业务任务;
- 推理 Kernel;
影响。最终必须用真实任务评估。
八、推理速度指标
TTFT
Time To First Token:
TTFT
≈ 排队
+ Tokenizer
+ Prefill
+ 第一次采样
输入越长,通常 TTFT 越大。
TPOT
Time Per Output Token:
TPOT = Decode总耗时 / 输出Token数
例如生成 100 Token 用时 5 秒:
TPOT = 5 / 100 = 0.05秒 = 50ms/token
Decode TPS
TPS = 1 / TPOT
上例:
TPS = 20 token/s
服务总吞吐
服务端还会统计所有并发请求的总 Token/s。它与单用户感受到的 Token/s 不是同一个指标。
九、计算上限与带宽上限
计算上限
Dense Transformer 每 Token 主干计算量可以粗估为:
[ FLOPs/token\approx2P_{\text{active}} ]
因此:
[ TPS_{\text{compute}} \approx \frac{GPU有效FLOPs/s}{2P_{\text{active}}} ]
对于 MoE,应使用每 Token 激活参数量估算计算,而不是总参数量。
Prefill 一次包含许多 Token,大矩阵乘法容易提高 GPU 利用率,通常更接近算力瓶颈。
带宽上限
Batch=1 Decode 每轮都要读取大量权重,可以粗略估算:
[ TPS_{\text{bandwidth}} \lesssim \frac{GPU有效显存带宽}{模型权重字节数} ]
假设:
有效显存带宽 = 2TB/s
模型权重 = 64GB
理想带宽上限:
2000GB/s ÷ 64GB
≈ 31 token/s
如果权重压缩到 16GB:
2000GB/s ÷ 16GB
≈ 125 token/s
这只是上限。实际还要扣除:
- KV Cache 读取;
- Attention 计算;
- 反量化;
- Kernel 效率;
- 多卡通信;
- 调度开销。
Decode 的实际上限可粗略理解为:
[ TPS \approx \min(TPS_{\text{compute}},TPS_{\text{bandwidth}}) ]
十、长上下文、Batch 和多卡
长上下文
有 KV Cache 后,历史 Token 不需要重新通过模型,但新 Query 仍需读取历史 K/V:
上下文长度5:读取5个位置
上下文长度32000:读取32000个位置
上下文越长,Decode 单 Token 的 KV 读取量越大,TPOT 通常会上升。
Batch
Batch 增大后,一次权重读取可以服务更多 Token:
Batch=1:读取权重,计算1个请求的新Token
Batch=16:读取权重,同时计算16个请求的新Token
所以总吞吐可能提高,但单请求延迟、KV Cache 和排队时间也可能增加。
多卡
Tensor Parallel 每层通常需要跨 GPU 聚合结果。NVLink 或高速互联下影响较小,PCIe 下通信可能成为瓶颈。多卡速度不会简单按 GPU 数量线性增加。
十一、量化不一定总是更快
低精度可能减少权重读取,但还要求:
- GPU 支持目标精度;
- 推理框架有成熟 Kernel;
- 模型格式受到支持;
- 反量化开销足够低;
- Batch 和矩阵尺寸适合该 Kernel。
某些不受支持的 INT4 格式需要频繁转换,可能不比 BF16 快。选择量化模型时,必须同时验证:
显存是否降低
TTFT是否改善
Decode TPS是否提升
输出质量是否可接受
十二、选择建议
| 目标 | 建议 |
|---|---|
| 追求原始质量 | BF16/FP16 |
| 显存减半且质量敏感 | 硬件支持时优先FP8/INT8 |
| 单卡部署更大模型 | 高质量AWQ/GPTQ INT4 |
| CPU或混合推理 | GGUF Q4/Q5/Q8 |
| 极低比特 | 优先选择经过QAT或专门优化的版本 |
| 长上下文 | 同时检查KV精度和KV Cache预算 |
一张 80GB GPU 的思路示例:
32B BF16:
权重精度高,但留给KV Cache的空间有限
70B INT4:
参数容量更大,权重约38~45GB,
可留下更多空间给KV Cache,但有量化误差
哪一个更好,取决于实际任务,而不是只看模型名称。
十三、正确的评测方式
比较不同精度时,应固定:
- 相同基础模型;
- 相同 Prompt 和 Chat Template;
- 相同最大长度;
- 相同采样参数;
- 相同数据集;
- 相同并发与 Batch;
- 相同推理框架版本。
至少记录:
模型加载后显存
最大KV Cache容量
峰值显存
TTFT
Prefill Token/s
Decode Token/s
任务准确率
长上下文召回
代码/数学指标
如果使用随机采样,应运行多次,不要只比较一条输出。
总结
参数量、精度和速度的关系可以概括为:
参数量决定模型容量
权重精度决定单参数存储和量化误差
权重字节数影响显存与Decode带宽
激活精度影响计算和临时显存
KV精度影响长上下文显存与注意力质量
Kernel和硬件决定低精度能否真正加速
绝大多数量化版本来自同一个高精度基础模型,通过 PTQ 和少量校准生成,不需要为每种精度重新预训练。固定显存下,最常见的取舍是“小模型高精度”与“大模型低精度”,最终应以真实业务质量和真实推理性能共同决定。