第17章:推理优化——KV Cache、量化与高效生成
系列导读:本章是 LLM 工程的核心技术之一。如果你要自建 LLM 服务或做推理调优,KV Cache 是必须理解的第一块基础。
一、LLM 推理有多贵?
GPT-4 处理一个 4000 token 的文档 + 生成 500 token 的答案,单次调用的推理成本是多少?
- Prompt token:每 token 都有成本
- 生成的每个 token:都要做一次完整的模型前向传播
- 长上下文:注意力计算是 O(n²),token 越多越慢
高频服务的推理成本会是最大的运营开销。优化不是锦上添花,是生死线。
二、KV Cache:为什么解码慢?
Transformer 在生成时有一个核心特性:自回归生成——每次只能生成一个 token。
假设你在生成第 K 个 token,模型需要:
- 把所有之前的 token 重新过一遍(包括你刚生成的第 K-1 个)
- 计算所有 token 的 Key 和 Value 向量
- 用这些 KV 做注意力,生成第 K 个 token
重复计算极大浪费。前面的 token 的 Key 和 Value 计算结果,在第 100 步和第 101 步怎么可能变?
KV Cache 的核心思想
缓存历史 token 的 Key 和 Value 向量,每步只计算新 token 的 KV。
# 没有 KV Cache(每次全量计算)
for i in range(max_new_tokens):
output = model(full_input + generated_tokens) # O(n²) 的注意力
next_token = sample(output)
generated_tokens.append(next_token)
# 有 KV Cache(只计算新内容)
for i in range(max_new_tokens):
# 只输入最新一个 token,KV Cache 提供历史注意力
output = model(next_token, past_key_values=kv_cache)
kv_cache.update(output.kv) # 新 token 的 KV 加入缓存
next_token = sample(output)
效果
- 时间复杂度:从 O(n²) → O(n)(每个新 token 的计算量几乎恒定)
- 速度提升:长上下文时提升数倍
- 内存消耗:需要额外存储所有历史 KV(通常几百 MB 到几 GB)
KV Cache 的容量压力
KV Cache 的大小 = 层数 × 注意力头数 × 序列长度 × 每头维度 × 2 (K+V) × 每个值精度
以 LLaMA-2-70B 为例:
- 80 层 × 8 KV 头 × 序列长度 4096 × 128 维度 × 2 × 2 bytes (FP16)
- ≈ 160 GB 内存 才能存放一个 batch_size=1 的 KV Cache
这就是为什么 长上下文 + 大 batch_size 的 LLM 推理内存需求极高。
三、量化推理(Quantization)
模型推理时的参数量极大(GPT-3 175B → ~350GB FP16),加载到 GPU 需要巨量显存。
量化:把模型权重从高精度(FP16/32)压缩到低精度(INT8/INT4),降低内存占用和计算带宽需求。
| 精度 | 每参数占存 | 效果影响 | 适用 |
|---|---|---|---|
| FP32 | 4 bytes | 基准 | 训练 |
| FP16/BF16 | 2 bytes | 几乎无损 | 推理 |
| INT8 | 1 byte | 轻微损失 | 推理 |
| INT4 | 0.5 bytes | 可观测损失 | 边缘/消费级 |
| GPTQ/AWQ | INT4 级 | 优化后接近 INT8 | 本地推理 |
GPTQ / AWQ / GGUF
这些是在 INT4 量级上做的高级量化技术,核心改进是:
- GPTQ:基于二阶 Hessian 信息做分组量化,误差更小
- AWQ:观察到"权重中 1% 离群值对效果影响极大",对离群值保持高精度
- GGUF:llama.cpp 的格式,CPU 推理友好,消费级 GPU 也能跑大模型
四、PagedAttention 与 vLLM
除了 KV Cache 和量化,还有一个革命性的推理优化:PagedAttention。
问题:KV Cache 的内存碎片
系统同时服务多个请求,每个请求的序列长度不同。显存分配像内存分配一样,会产生碎片。
传统做法:每个请求预分配最大可能的 KV Cache 空间 → 大量内存浪费。
PagedAttention 的思路
借鉴操作系统虚拟内存的分页机制:
- 把 KV Cache 切成固定大小的 “block”(比如 16 token 一组 KV)
- 按需要的块动态分配和回收
- 用 block table 做虚拟到物理的映射
效果:
- 内存碎片化几乎消除
- batch size 可以提升数倍
- 吞吐量提升 3-5 倍(论文数据)
vLLM:基于 PagedAttention 的高性能推理引擎,是自建 LLM 服务的首选开源框架。
五、推理优化的决策树
你要优化推理?先看你的瓶颈:
内存不够? → 量化(FP16→INT8或INT4)
速度不够? → KV Cache + PagedAttention (vLLM)
并发不够? → 批处理优化(continuous batching)
长上下文慢? → KV Cache + 稀疏注意力 / 滑动窗口注意力
网络延迟? → 流式输出(SSE)+ 输出压缩
六、本章小结
- KV Cache 是 LLM 推理加速的第一性原理:避免重复计算历史 token
- KV Cache 的内存消耗极大,是大 batch / 长上下文推理的主要瓶颈
- 量化(FP16/INT8/INT4)是压缩模型体积的最有效手段
- PagedAttention 用分页管理 KV Cache,消除碎片、提升吞吐量
- vLLM 结合了 KV Cache + PagedAttention + 高效调度,是当前主流的高性能推理方案
思考题
- KV Cache 的内存占用和 batch_size 成正比。如果要在单卡 24GB 显存上实现比较大的并发,你会从哪些角度做取舍设计?
- 量化到 INT4 后精度损失最大的是哪些类型的权重?为什么 Transformer 的注意力层权重比较敏感?