模型量化与推理加速
校招考察频度:低频拓展(大模型工程化落地与推理优化·面试加分项) 复习主线:对于大部分算法与智能体研发岗,模型训练(SFT/RLHF)可能由少数基础团队负责,但模型的低成本部署、显存控制与高并发推理吞吐是每位后端与 Agent 工程师直接面临的生产问题。核心重点:显存带宽瓶颈(Memory-Bound)、权重量化原理(INT8/INT4/AWQ/GPTQ)、推测采样(Speculative Decoding)与连续批处理(Continuous Batching)。
1. 为什么大模型推理如此昂贵?
在深入量化之前,必须先理清大模型推理的性能瓶颈所在:
1.1 显存容量瓶颈(Capacity Bound)
- 1 个参数在 FP16(半精度浮点)下占用 2 个字节(Bytes)。
- 一个 70B(700 亿参数)模型,光加载模型静态权重就需要:
70 * 10^9 * 2 Bytes ≈ 140 GB显存! - 加上自回归推理必须保存的历史会话 KV Cache,至少需要 2 张昂贵的 80GB A100/H800 显卡才能跑起来。
1.2 显存带宽瓶颈(Memory Bandwidth Bound)
- Prefill 阶段(首字生成·计算密集):把 Prompt 一次性送入,矩阵乘法吞吐高,受限于 GPU 算力(Compute-Bound)。
- Decode 阶段(逐字生成·显存带宽密集):大模型是自回归的,每吐出一个 Token,都需要把整个模型的全部权重(例如 140GB)从 GPU 显存(HBM)完整搬运到计算核心(SRAM/ALU)一次,而这次计算仅仅是为了生成 1 个 Token!
- 绝大多数时间 GPU 算力核心都在“饥饿等待”显存数据的送达。因此,减少权重体积、降低搬运数据量,就能直接成倍提升解码吞吐!
2. 大模型量化(Quantization)技术
量化的核心思想:用更低精度的数值类型来近似表示高精度的模型权重和激活值,牺牲极微小的精度,换取显存的大幅缩减与计算加速。
2.1 数值类型精度与显存对比
| 精度类型 | 占用字节数 | 动态范围与特点 | 70B 模型权重所需显存 |
|---|---|---|---|
| FP32 | 4 Bytes (32 bit) | 传统深度学习训练精度,范围大,显存消耗极高 | 约 280 GB |
| FP16 / BF16 | 2 Bytes (16 bit) | 大模型标准预训练与推理精度(BF16 防止下溢) | 约 140 GB |
| INT8 / FP8 | 1 Byte (8 bit) | 几乎无精度损失,主流英伟达 Ada/Hopper 架构硬件原生支持 | 约 70 GB |
| INT4 | 0.5 Byte (4 bit) | 压缩极限,主流消费级显卡部署方案(如 AWQ/GPTQ) | 约 35 GB |
2.2 线性量化数学原理
线性量化将浮点实数范围 [x_min, x_max] 映射到定点整数范围(如 INT8 的 [-128, 127]):
量化公式: q = clip( round( x / Scale ) + ZeroPoint, q_min, q_max )
反量化公式: x_approx = ( q - ZeroPoint ) * Scale- Scale(缩放因子):步长,决定浮点数到整数的比例缩放。
- ZeroPoint(零点偏移):浮点数 0.0 在整数坐标系中的对应位置。
- 对称量化 vs 非对称量化:
- 对称量化:
ZeroPoint = 0,以 0 为对称轴,计算效率高(常用于权重 Weight)。 - 非对称量化:
ZeroPoint ≠ 0,适用于数值分布极度偏向正轴的场景(常用于激活值 Activation)。
- 对称量化:
2.3 PTQ(训练后量化)主流算法对比
大模型重新全量微调量化(QAT)成本太高,目前工业界绝大多数采用 PTQ(Post-Training Quantization):
| 算法 | 核心思想 | 优势与局限 |
|---|---|---|
| Naive Round-to-Nearest (RTN) | 直接四舍五入舍入到最近的整数 | 简单快速,但对于低于 8bit(如 4bit)会造成严重模型崩溃 |
| GPTQ | 基于二阶逆 Hessian 矩阵,逐层对量化产生的误差进行数学补偿补偿 | 压缩率高,INT4 精度恢复极好;需要少量校准集跑逆矩阵计算 |
| AWQ (Activation-aware) | 发现只有 1% 的显著权重(Salient Weights) 对输出起决定性作用,通过激活值分析保护这 1% 的通道不被破坏 | 泛化能力优于 GPTQ,对长文本与代码生成场景更鲁棒,推理开销更低 |
| GGUF / llama.cpp | 端侧量化文件格式,支持 k-quant 混合精度(部分重要层 6bit,非关键层 4bit) | 专为 CPU/Mac Metal 优化,个人电脑与本地离线部署之王 |
3. 推理系统加速关键技术
大模型服务框架(如 vLLM、TGI、TensorRT-LLM)相比直接用原生 PyTorch 跑推理,吞吐能提升 5~10 倍。核心依托以下三大技术:
3.1 PagedAttention(显存分页管理)
- 传统痛点:原生 PyTorch 必须为每个请求提前预分配一块连续的显存来存放未来可能用到的全部 KV Cache(如预分配 4K Token 的连续空间)。这导致大量的显存碎片和未用预留浪费,实际显存有效利用率仅 20%~40%。
- 核心创新:借鉴操作系统虚拟内存分页机制,将 KV Cache 切分成固定大小的“物理块(Block)”(例如每个 Block 存放 16 个 Token)。
- 效果:KV Cache 无需在物理显存上连续存放,通过逻辑 Block 表动态映射,彻底消除碎片,显存利用率飙升至 96% 以上,并发吞吐成倍提升。
3.2 连续批处理(Continuous Batching / In-flight Batching)
- 传统 Static Batching:一个批次里有 4 个请求,请求 A 生成 10 个词就结束了,但请求 B 需要生成 500 个词。A 必须一直在旁边干等、填充
PAD符号,直到 B 彻底完成,GPU 算力极度浪费。 - 连续批处理:以 Iteration(单词迭代) 为粒度调度。当请求 A 完成的瞬间,引擎立即将其剔除,并将等待队列中的新请求 C 插入进当前的 Iteration。GPU 矩阵计算核心永远处于饱满状态。
传统 Static Batching:
Req 1: [Token 1][Token 2][PAD][PAD][PAD]... (浪费等待)
Req 2: [Token 1][Token 2][Token 3][Token 4][Token 5]...
连续批处理 (Continuous Batching):
Iteration 1: [Req 1 - T1] [Req 2 - T1]
Iteration 2: [Req 1 - T2] [Req 2 - T2] (Req 1 结束, 立即换入 Req 3)
Iteration 3: [Req 3 - T1] [Req 2 - T3]3.3 推测采样(Speculative Decoding / 投机采样)
如何让 70B 模型跑出 7B 模型的推理速度,且输出质量 100% 保持数学等价?
+-----------------------------+
| 小模型 (Draft: 1B/3B) |
+-----------------------------+
|
快速自回归预测 K 个 Token
(耗时极短,如预测 4 个 Token)
v
[Token A] -> [Token B] -> [Token C] -> [Token D]
|
v (一次 Forward 送入)
+-----------------------------+
| 大模型 (Target: 70B) |
+-----------------------------+
|
并行验证 4 个 Token 的概率分布
(接受 A, B, 拒绝 C, 修正输出 C')
v
最终输出: A -> B -> C'- 原理:
- 用一个轻量级的小模型(Draft Model,如 1B 参数)快速自回归生成
K个候选 Token(比如 4 个)。 - 将这 4 个 Token 打包,通过大模型(Target Model,如 70B 参数)仅做一次前向传播(Forward),并行计算这 4 个位置的真实条件概率。
- 大模型基于拒绝采样算法决定接受前几个 Token。只要小模型猜对了哪怕 2
3 个,大模型就用 1 次前向的耗时吐出了 34 个 Token!
- 用一个轻量级的小模型(Draft Model,如 1B 参数)快速自回归生成
- 特性:完全无损。最终概率分布严格收敛于大模型本身的输出分布,速度提升 2~3 倍。
4. 显存核算速算公式(面试速记)
面试常问:“如果我们要部署一个 Qwen-72B 模型,支持并发为 10,每个会话上下文 4096,需要几张 80G 的 A100?”
总显存消耗 = 模型权重显存 + 运行时 KV Cache 显存 + 激活值与 CUDA 预留- 权重显存:
- 72B FP16:
72 * 2 = 144 GB(需要至少 2 张 80G A100)。 - 72B INT4(AWQ):
72 * 0.5 = 36 GB(仅需 1 张 80G A100 或 2 张 24G 4090)。
- 72B FP16:
- KV Cache 显存估算公式:
- 每个 Token 的 KV Cache 字节数:
Bytes_per_token = 2 (K+V) * num_layers * hidden_size * sizeof(precision)(若使用 GQA 分组查询注意力,还要除以组数压缩比)。 - 通常经验法则:1 个 70B 模型下,每个用户 1K 上下文约消耗 0.5GB ~ 1GB 显存。
- 每个 Token 的 KV Cache 字节数:
5. 面试高频追问
Q1:为什么量化通常只量化权重(Weight-Only),而不量化激活值(Activation)?
答:
- 激活值存在离群值(Outliers):大模型各层输出的特征激活值中,极少部分通道的幅值会突然比平均值高出数十倍甚至上百倍。如果采用全局非对称量化压到 INT8,这些离群值会拉大 Scale,把正常绝大多数数值全部压缩到同一桶中导致精度断崖下跌。
- 硬件支持限制:传统 GPU(如 V100/A100)的 Tensor Core 原生支持 FP16 计算。Weight-Only 量化(如 W4A16)可以在显存中只存 4bit 权重,在搬入计算核心时动态反量化为 FP16,从而享受完整的显存带宽节省与大显存利用率,工程实现最成熟。现代 Hopper/Ada 架构(H100/RTX 4090)才正式硬件级支持 FP8/INT8 的 GEMM 矩阵乘法加速。
Q2:推测采样(Speculative Decoding)在什么场景下加速最明显?什么场景下会失效?
答:
- 加速最明显:文本规律性极强、模式可预测的场景,例如代码续写(标准语法、缩进、常见库函数)、通用问答中的连接词与套话。此时小模型的预测命中率可高达 80%
90%,加速比达到 2.5x3x。- 失效场景:高发散性创作、复杂数学推理(CoT 关键跳跃步)。小模型很容易猜错第一个 Token,大模型从第一个 Token 就直接拒绝,导致每次只生成 1 个 Token 还白白浪费了小模型的草稿计算时间,加速比降到 1.0x 甚至微弱负优化。