第17章:推理优化——KV Cache、量化与高效生成

第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,模型需要:

  1. 把所有之前的 token 重新过一遍(包括你刚生成的第 K-1 个)
  2. 计算所有 token 的 Key 和 Value 向量
  3. 用这些 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 + 高效调度,是当前主流的高性能推理方案

思考题

  1. KV Cache 的内存占用和 batch_size 成正比。如果要在单卡 24GB 显存上实现比较大的并发,你会从哪些角度做取舍设计?
  2. 量化到 INT4 后精度损失最大的是哪些类型的权重?为什么 Transformer 的注意力层权重比较敏感?