跳到主要内容

第22章:进阶推理优化

上一章我们探讨了 KV Cache 和 Continuous Batching 等基础推理优化手段。但在实际生产环境中,工程师们面临的挑战远不止于此:如何在保持输出质量的同时将延迟压缩到极限?如何让一块消费级 GPU 运行起 70B 的大模型?如何把计算资源分配得更精准?

本章深入四个进阶方向:投机采样、Prefill/Decode 分离、模型量化,以及主流推理框架的横向对比。


22.1 投机采样(Speculative Decoding)

核心矛盾:精度与速度不可兼得?

大模型(如 70B)输出质量高,但自回归逐 token 生成极慢——每生成一个 token 都要做一次完整的前向传播。小模型(如 7B)速度快,但输出质量较差。

一个自然的问题:能否让小模型先"猜"一批 token,再让大模型"验",从而用一次大模型前向传播换来多个 token?

这就是投机采样(Speculative Decoding)的核心思想,由 Google 和 DeepMind 分别于 2022-2023 年独立提出。

草稿模型(Draft Model)

小模型被称为草稿模型(Draft Model)。它以自回归方式快速生成 KK 个候选 token,形成一条"草稿序列":

x~t+1,x~t+2,,x~t+K\tilde{x}_{t+1}, \tilde{x}_{t+2}, \ldots, \tilde{x}_{t+K}

草稿模型的生成过程与普通解码完全相同,只是模型参数量小得多,速度快 5-10 倍。

目标模型(Target Model)与并行验证

关键洞察在于:大模型可以对一段序列进行并行的前向传播——输入 KK 个位置,同时得到 KK 个位置的概率分布,时间复杂度与处理单个 token 相当(受益于 Transformer 的并行性)。

目标模型(Target Model,即大模型)接收完整序列,对草稿的每个位置 t+it+i 计算其概率分布 ptarget(x1:t+i1)p_{\text{target}}(\cdot \mid x_{1:t+i-1})

验证机制:接受-拒绝采样

对草稿序列中每个 token x~t+i\tilde{x}_{t+i},执行以下判断:

acceptifuptarget(x~t+i)pdraft(x~t+i),uUniform(0,1)\text{accept} \quad \text{if} \quad u \leq \frac{p_{\text{target}}(\tilde{x}_{t+i})}{p_{\text{draft}}(\tilde{x}_{t+i})}, \quad u \sim \text{Uniform}(0, 1)
  • 若接受(accept):保留该 token,继续验证下一个
  • 若拒绝(reject):从调整后的分布中重新采样一个 token,并丢弃后续所有草稿 token

重采样使用的修正分布为:

pcorrected(x)=normalize ⁣(max ⁣(0,ptarget(x)pdraft(x)))p_{\text{corrected}}(x) = \text{normalize}\!\left(\max\!\left(0,\, p_{\text{target}}(x) - p_{\text{draft}}(x)\right)\right)

:::info 为什么这个机制保证了输出分布等价? 可以证明,经过上述接受-拒绝过程,最终生成序列的概率分布与单独使用目标模型(大模型)完全一致。投机采样是无损加速——不牺牲任何输出质量。 :::

加速原理

假设草稿 token 的平均接受率为 α\alpha,草稿序列长度为 KK,则每次大模型前向传播平均产生的有效 token 数为:

E[accepted tokens]=1αK+11α\mathbb{E}[\text{accepted tokens}] = \frac{1 - \alpha^{K+1}}{1 - \alpha}

α=0.8\alpha = 0.8K=4K = 4 时,期望接受数约为 3.36 个 token——相比原来每次只生成 1 个,吞吐量提升约 3 倍。

实际工程中,投机采样在 Llama 系列上可实现 2-3× 吞吐量提升,延迟降低尤为明显。

自投机采样(Self-Speculative Decoding)

一个更优雅的变体:不需要单独的小模型,而是用同一大模型的早期层作为草稿模型。

具体做法是让模型在某个中间层(如第 16 层)提前输出一个 token 概率分布,作为草稿;完整的 32 层输出作为目标分布进行验证。这样无需维护额外模型,部署更简单。


22.2 Prefill / Decode 分离(PD Disaggregation)

两种截然不同的计算模式

一次 LLM 推理分为两个阶段:

阶段输入计算特征瓶颈
Prefill整个 prompt(可能数千 token)矩阵乘法密集,GPU 算力满载计算(Compute-bound)
Decode单个 token(逐步生成)频繁读写 KV Cache,计算量小内存带宽(Memory-bound)

当两者混跑在同一个 GPU 上时,问题来了:

  • 一个大 Prefill 请求会独占 GPU 数秒,导致其他 Decode 请求被"卡住",出现长尾延迟(P99 延迟飙升)
  • Prefill 和 Decode 的最优批处理策略完全不同,无法同时满足

:::warning 干扰效应(Interference) 这不是小问题。在长 prompt 场景(如 RAG 检索增强、文档摘要),一次 Prefill 可能耗时超过 5 秒,此时所有 Decode 请求全部阻塞,用户看到的是长时间"没有响应"。 :::

PD 分离架构

解决方案是将 Prefill 和 Decode 部署在不同的 GPU 集群上:

用户请求


┌─────────────┐ KV Cache ┌─────────────┐
│ Prefill 集群 │ ─────────────── ► │ Decode 集群 │
│ (算力优化) │ 高速网络传输 │ (带宽优化) │
└─────────────┘ └─────────────┘
  • Prefill 节点:计算整个 prompt 的 KV Cache,使用大 batch 和高算力 GPU(如 H100)
  • Decode 节点:接收 KV Cache,逐 token 生成,使用内存带宽更高的 GPU(如 A100)
  • KV Cache 传输:通过 NVLink、InfiniBand 或 RDMA 高速网络传输,通常在毫秒级完成

代表实现

Mooncake(月之暗面,2024):将 KV Cache 传输延迟与 Decode 计算重叠(overlap),通过"以传代算"减少 Decode 等待时间。同时设计了分布式 KV Cache 池,支持跨节点共享前缀缓存。

DistServe(2024):系统性分析了 PD 分离的资源配比问题,提出根据实际请求负载动态调整 Prefill:Decode 节点比例。

:::tip 效果 PD 分离在长 prompt 场景下(prompt 长度 > 1000 token),P99 延迟可降低 40-60%,首 token 时间(TTFT, Time To First Token)和生成吞吐量同时改善。 :::


22.3 模型量化(Model Quantization)

为什么需要量化:显存的铁幕

一个直接的计算:FP16(16 位浮点数)格式下,模型权重每个参数占 2 字节。7B 模型有 70 亿参数,仅权重就需要 14GB 显存,加上 KV Cache 和激活值,往往需要 24GB 以上的 GPU。

量化(Quantization)将权重从高精度降到低精度:

格式每参数字节7B 模型权重大小备注
FP324 bytes28 GB训练常用
FP16 / BF162 bytes14 GB推理标准
INT81 byte7 GB精度几乎无损
INT40.5 bytes3.5 GB轻微质量下降
INT20.25 bytes1.75 GB质量损失较大

INT4 量化可让 7B 模型在单张 4GB 显存的 GPU 上运行——这使消费级硬件成为可能。

权重量化 vs 激活量化

权重量化(Weight Quantization):对模型权重矩阵做量化。权重在推理时不变,可以离线精确校准,难度较低。

激活量化(Activation Quantization):对前向传播中的中间激活值做量化。激活值随输入动态变化,存在异常值(outliers),量化难度大得多。

大多数实用方案选择仅做权重量化(Weight-Only Quantization),计算时将权重反量化回 FP16 再做矩阵乘法,或使用混合精度内核直接完成量化矩阵乘法。

GPTQ(2022):基于 Hessian 的逐层量化

GPTQ 的核心思想是逐层最小化量化误差。对于某一层权重矩阵 WW,找到量化后的 W^\hat{W},使得:

minW^WXW^XF2\min_{\hat{W}} \left\| WX - \hat{W}X \right\|_F^2

其中 XX 是该层的输入激活(使用少量校准数据计算)。

GPTQ 利用 Hessian 矩阵 H=2XXH = 2XX^\top 来决定量化顺序和误差补偿:量化某个权重后,将其误差"传播"给同行的其他权重(Optimal Brain Compression 思想)。

这样在 INT4 精度下,Llama-2 70B 的困惑度(Perplexity)相比 FP16 仅上升约 0.1-0.3,几乎可以忽略。

AWQ(2023):保护重要权重

AWQ(Activation-aware Weight Quantization)的洞察是:不同权重对输出质量的重要性差异极大——与激活值幅度相关性高的权重(即"重要权重")一旦量化误差过大,对输出质量影响是灾难性的,仅占权重总数的 0.1-1%。

AWQ 的策略:

  1. 通过校准数据统计每个权重通道对应的激活幅度 ss
  2. 对重要权重(高激活幅度对应的权重)进行缩放保护:量化前将权重除以 ss,从而在量化步长固定时,重要权重获得更高的相对精度
  3. 其余权重正常激进量化到 INT4
W^=quant ⁣(Ws)s\hat{W} = \text{quant}\!\left(\frac{W}{s}\right) \cdot s

AWQ 无需 GPU 反向传播,量化速度比 GPTQ 快约 10 倍,且在多数基准上精度更高。它是目前 llama.cpp 和 vLLM 生产部署中最常用的量化方案之一。


22.4 主流推理框架对比

推理框架的选择对系统性能影响巨大。当前主流框架各有侧重,适合不同场景。

vLLM

核心技术:PagedAttention + Continuous Batching(详见第 21 章)

  • 优势:吞吐量业界最高,支持几乎所有主流开源模型,社区活跃,API 兼容 OpenAI
  • 局限:多轮对话场景中前缀缓存(Prefix Caching)命中率有限;冷启动较慢
  • 适用场景:高并发在线推理服务、API 网关
# vLLM 典型用法
from vllm import LLM, SamplingParams

llm = LLM(model="meta-llama/Llama-3-8B-Instruct")
outputs = llm.generate(["Hello, my name is"], SamplingParams(max_tokens=50))

TGI(Text Generation Inference)

开发方:Hugging Face

  • 优势:工程成熟,与 HuggingFace Hub 生态深度集成,Docker 部署极简,支持 Tensor Parallelism
  • 局限:吞吐量略低于 vLLM,定制化扩展难度较大
  • 适用场景:快速原型验证,HuggingFace 生态用户,需要稳定企业支持的场景

SGLang

核心技术:RadixAttention(基数树前缀缓存)

RadixAttention 将 KV Cache 组织为一棵基数树(Radix Tree),不同请求共享相同前缀的 KV 只需计算一次。对于以下场景命中率极高:

  • System prompt 固定的多轮对话(所有用户共享同一 system prompt 的 KV)
  • Few-shot 样例固定的批量推理(所有样本共享 demonstration 部分)
  • RAG 场景中重复出现的文档片段
System Prompt(共享) ──┐
├── 用户A的对话
├── 用户B的对话
└── 用户C的对话
  • 优势:共享前缀场景下 TTFT 降低 50-80%,结构化输出(JSON mode)支持出色
  • 适用场景:Agent 框架、多轮对话服务、批量推理

llama.cpp

核心技术:纯 C++ 实现,GGUF 格式量化权重

  • 优势:可在 CPU 上运行,支持 Apple Silicon (Metal)、NVIDIA (CUDA)、AMD (ROCm) 等多种硬件;INT4/INT2 量化生态最完善;内存占用极低
  • 局限:吞吐量远低于 GPU 专用框架,不适合高并发服务
  • 适用场景:本地开发测试、边缘设备、无 GPU 环境、个人电脑运行大模型

选型建议

场景推荐框架核心理由
高并发 API 服务(无共享前缀)vLLM吞吐量最优,生态完善
多轮对话 / Agent(固定 system prompt)SGLangRadixAttention 大幅降低重复计算
快速部署,HuggingFace 模型TGI一键 Docker,集成度高
本地运行 / 边缘设备 / 无 GPUllama.cpp跨平台,CPU 友好
需要 PD 分离的超大规模集群vLLM + Mooncake生产级分布式推理

本章小结

技术核心思想典型收益代价
投机采样(Speculative Decoding)小模型猜,大模型验延迟降低 2-3×需要维护草稿模型
PD 分离(PD Disaggregation)Prefill 和 Decode 专机专用P99 延迟降低 40-60%需要高速网络互联
GPTQ 量化Hessian 引导的逐层误差最小化INT4 精度损失 < 1%量化耗时较长
AWQ 量化保护高激活相关权重INT4 精度更高,速度更快需要少量校准数据
vLLMPagedAttention + 连续批处理吞吐量最优前缀场景不占优
SGLangRadixAttention 前缀树复用共享前缀场景延迟极低非共享场景收益有限
llama.cppC++ CPU 推理 + GGUF 量化零 GPU 运行大模型吞吐量低

推理优化的本质是在延迟、吞吐量、显存三个维度之间寻找帕累托最优解。没有万能银弹,只有根据场景特征做出的工程权衡。


到目前为止,我们讨论的都是如何更快、更省地运行一个已有的模型。但如果你的业务场景高度特殊,通用的预训练模型无法满足需求,又不想从头训练——这就引出了下一章的主题:高效微调(Fine-tuning),以及如何用极少的参数更新让大模型适配特定领域。