为什么推理优化越来越重要

训练一次大模型成本高,但跑起来之后每天都要服务大量用户,长期来看推理成本远高于训练成本。一个 70B 模型如果用 FP16 直接跑,单卡 A100 80G 都装不下,更不用说提供低延迟服务。所以推理优化不是锦上添花,而是落地的前提

下面整理几个工程上最常用、收益最显著的优化方向。

1. KV Cache 是性能的核心

Transformer 自回归生成时每生成一个 token 都要重新计算所有历史 token 的 K 和 V,这是 O(n²) 的浪费。KV Cache 把之前算过的 K/V 缓存下来,每步只算新 token 的 K/V,复杂度降到 O(n)。

但 KV Cache 本身会吃巨量显存:一个 13B 模型、序列长度 4K、batch 16,KV Cache 就要十几 GB。所以衍生出一系列优化:

  • PagedAttention(vLLM 提出):把 KV Cache 按"页"管理,避免连续显存碎片化,吞吐能提 2-4 倍
  • GQA / MQA:让多个 Query Head 共享同一组 K/V Head,KV Cache 大小直接砍几倍,Llama 3 就用了 GQA
  • 量化 KV Cache:把 KV Cache 从 FP16 量化到 INT8 甚至 INT4,显存减半但精度损失很小

2. 量化:用精度换显存和速度

权重量化的核心思路是:模型权重是 FP16 (16 bit),但实际有效信息可能只需要 4 bit 就能表达。常见方案:

方案位宽特点
GPTQ4 bit训练后量化,精度高,主流方案
AWQ4 bit保留重要权重通道为高精度,效果略好于 GPTQ
GGUF (llama.cpp)2-8 bitCPU/Metal 友好,本地部署首选
FP88 bitH100 原生支持,精度损失极小

实测 4 bit 量化的 70B 模型在大部分中文任务上和 FP16 差距不到 1 个百分点,但显存占用从 140G 降到 35G,单卡 A100 即可部署。

3. 投机采样:用小模型加速大模型

Speculative Decoding 的思路非常巧妙:让一个小模型(draft model)连续生成 n 个候选 token,再用大模型一次性并行验证这 n 个 token,接受其中前 k 个正确的。

这样大模型一次 forward 能产生多个 token,平均 latency 降低 2-3 倍,且输出和直接用大模型完全一致(数学上等价)。

限制是小模型需要和大模型分布接近,否则接受率太低反而变慢。Llama 3 8B + Llama 3 70B 是经典搭配。

4. Continuous Batching

传统批处理:等齐 N 个请求再一起跑,最快的请求要等最慢的请求结束才能拿到结果。

Continuous Batching(也叫 In-flight Batching):每生成完一个 token 就检查队列,结束的请求出队、新请求入队,永远保持 batch 满载。vLLM、TGI、TensorRT-LLM 都用这个调度策略。

效果是吞吐能提 2-10 倍,尤其在请求长度差异大的场景。

5. 编译优化与图融合

把 PyTorch 的动态图编译成静态图能省下解释器开销。常用工具:

  • torch.compile:PyTorch 2.0 内置,开箱即用,对常规模型有 20-50% 加速
  • TensorRT-LLM:NVIDIA 官方,性能最强但写起来复杂
  • vLLM:综合方案,工程友好,社区活跃

实践中 vLLM 是大部分团队的默认选择 —— 不是单项最快,但综合性能、易用性、社区支持最佳。

写在最后

推理优化没有银弹,需要根据业务场景组合:

  • 延迟敏感(如对话):优先 Speculative Decoding + GQA
  • 吞吐敏感(如批量摘要):优先 Continuous Batching + 量化
  • 显存吃紧(消费级 GPU):优先 GGUF 量化 + KV Cache 量化

下一篇会写 vLLM 的具体部署和调优经验。