跳转至

推理优化

概述

推理优化让 AI 模型在生产环境中运行得更快、更省钱。对于基础模型——尤其是自回归 LLM——推理本身就代价高昂:生成每一个输出 token 都需要把完整的模型权重加载进 GPU 内存,且 token 是顺序产生的。这带来了随模型规模增长的延迟和成本压力。优化技术从模型层面和推理服务层面两方面来化解这些瓶颈。

如果你使用托管 API(OpenAI、Anthropic、Google),大部分工作由提供方处理。如果你自托管模型,推理优化就成了你自己的责任。

理解瓶颈

计算受限 vs. 内存带宽受限

瓶颈 成因 出现时机
计算受限 完成时间受限于算术运算 预填充阶段(并行处理输入 token);图像生成
内存带宽受限 完成时间受限于内存与计算单元之间的数据传输速率 解码阶段(顺序生成输出 token);大多数 LLM 推理

对于自回归 LLM,解码是内存带宽受限的:每生成一个 token 都要从 GPU 内存加载整个模型的权重矩阵,却只用它们做极少量的计算(一个 token)。这意味着 GPU 在解码期间没有被充分利用。

预填充 vs. 解码

Prefill: process all input tokens simultaneously → compute-bound
Decode: generate output tokens one by one → memory-bandwidth-bound

在生产中,这两个阶段常被解耦、跑在不同机器上(预填充机器与解码机器的优化取向不同)。首 token 时延(TTFT)主要取决于预填充;每个输出 token 时延(TPOT)取决于解码。

推理性能指标

指标 定义 目标
TTFT(首 token 时延) 从查询到生成第一个 token 的时间 对话场景应尽可能低;长文档摘要场景用户可接受更长等待
TPOT(每个输出 token 时延) 生成后续每个 token 的时间 约 120 毫秒/token(8 token/秒)已足够大多数阅读速度
总延迟 TTFT + TPOT × 输出 token 数 取决于应用
吞吐量(TPS) 所有用户合计每秒输出的 token 数 越高成本越低
有效吞吐(Goodput) 每秒满足 SLO(延迟目标)的请求数 对真实应用真正重要的指标
MFU(模型 FLOP 利用率) 实测吞吐 / 理论峰值吞吐 衡量 GPU 算力利用效率
MBU(模型带宽利用率) 已用内存带宽 / 峰值带宽 衡量内存利用效率

延迟是一个分布,而非一个数字。应使用 p50、p95、p99,而非平均值。离群值意味着问题(网络错误、超长提示)。

批处理 API vs. 在线 API:许多提供方为 SLO 长达数小时的批处理 API 提供 50% 的成本折扣,适合合成数据生成、周期性报表、重建索引等。在线 API 则用于面向客户的场景。

模型层面的优化

量化

降低模型权重的数值精度(例如从 32 位浮点降到 8 位或 4 位整数):

方法 说明 权衡
仅权重量化(W8、W4) 量化权重,激活值保持较高精度 最广泛使用;8 位时质量损失极小,4 位时有一定损失
激活量化(W8A8) 同时量化权重和激活值 实现更难;在兼容硬件上算术运算更快
KV 缓存量化 将 KV 缓存量化为 int8 或 fp8 减轻内存压力;支持更长序列
QLoRA 先量化基座模型再加 LoRA 适配器 使大模型在消费级 GPU 上的微调成为可能

仅权重量化是最常见的做法:FP32→FP16 使内存占用减半;FP16→INT8 再减半。低于 4 位时,质量会显著退化。

剪枝

从训练好的模型中移除不必要的参数(连接或整个节点): - 非结构化剪枝:将单个权重置零 → 稀疏模型;并非所有硬件都能从稀疏性中获益 - 结构化剪枝:移除整个神经元/层 → 更小的模型;对硬件友好 - 截至 2024 年,由于复杂度较高、收益较小,剪枝在实践中不如量化常用

知识蒸馏

训练一个较小的"学生"模型去模仿较大"教师"模型的输出。在特定任务上,学生模型能以少得多的参数达到与教师相当的质量。提供方(如 GPT-4 蒸馏出的模型)和应用团队都会用它来做对延迟敏感的部署。

投机解码(Speculative Decoding)

用以克服自回归解码的顺序瓶颈:

  1. 一个快速的小型草稿模型并行生成 K 个候选 token
  2. 目标模型同时验证全部 K 个 token(可并行,因而快)
  3. 保留最长的被接受前缀;目标模型再生成一个额外的 token
  4. 重复

为何有效:验证比生成快(并行 vs. 顺序),而"容易"位置(常见词、重复模式)上的草稿 token 被接受的比例很高。对于代码生成,接受率尤其高。DeepMind 用一个 4B 草稿模型让 Chinchilla-70B 的延迟降低了 2 倍以上。

投机解码现已在 vLLM、TensorRT-LLM 和 llama.cpp 中可用。

注意力机制优化

transformer 的注意力机制在序列长度上具有 O(n²) 复杂度——它是长上下文场景的主要瓶颈。

KV 缓存

在生成第 t+1 个 token 时,模型无需为第 1 到第 t 个 token 重新计算键(key)和值(value)向量——它们可以被缓存并复用。这就是 KV 缓存

  • KV 缓存大小随序列长度和批大小线性增长
  • 对于一个 96 层、96 个注意力头、头维度 128、序列长度 2048 的模型:批大小为 512 时,FP16 下 KV 缓存 ≈ 3TB
  • 管理 KV 缓存是推理工程的核心挑战之一

KV 缓存优化

技术 说明
PagedAttention(vLLM) 用非连续的内存页管理 KV 缓存(类似操作系统的虚拟内存);消除碎片;支持动态分配
分组查询注意力(GQA) 多个查询头共享键/值头;在质量损失极小的前提下将 KV 缓存缩小 4–8 倍
多查询注意力(MQA) 极端版本:所有查询共享一个键/值头
跨层注意力 某些层共享相邻层的键/值;Llama 3.1 借此将 KV 缓存缩小 20 倍
滑动窗口注意力 只关注最近的 W 个 token;同时减少 KV 缓存与计算量
KV 缓存量化 以更低精度(int8/fp8)存储 KV 缓存

FlashAttention

一种硬件优化的核(kernel),它融合多个注意力操作以减少内存读写。在现代 NVIDIA GPU(A100、H100)上,FlashAttention-2 和 FlashAttention-3 相比标准注意力带来 2–3 倍加速。大多数现代推理框架默认使用它。

提示词缓存

如果许多请求共享相同的系统提示词或文档前缀,就可以存储并复用该前缀的 KV 缓存。提供方(Anthropic、Google)提供显式的提示词缓存 API,对缓存 token 有约 90% 的成本折扣。对于带有大量固定上下文的 RAG 系统尤为有价值。

推理服务的优化

连续批处理(Continuous Batching)

朴素批处理会等到一批凑满才开始。连续批处理则在有空位时立刻处理新请求——类似网约车在座位空出时随即接上新乘客。这样可以: - 最大化 GPU 利用率 - 减少排队延迟 - 支持变长序列而不因填充而浪费

vLLM、TGI 及大多数现代推理框架都在使用它。

预填充-解码解耦(Prefill-Decode Disaggregation)

用专门的机器分别处理预填充(计算受限)和解码(带宽受限)阶段: - 预填充机器针对并行计算优化 - 解码机器针对内存带宽优化 - 减少两阶段间的相互干扰;可独立改善 TTFT 与吞吐量

并行策略

对于单块 GPU 装不下的模型:

策略 说明 适用场景
张量并行 将单个权重矩阵切分到多块 GPU;需要高速互连 单节点多 GPU
流水线并行 将不同层分配到不同 GPU;会引入流水线气泡 多节点部署
数据并行 运行模型的多个副本;将不同请求路由到不同副本 高吞吐、推理服务
专家并行 针对 MoE 模型:每块 GPU 托管一部分专家 混合专家推理

主要推理框架

框架 优势
vLLM PagedAttention、连续批处理、投机解码;采用广泛
TensorRT-LLM NVIDIA 优化;核融合、INT8/FP8 量化;在 H100 上吞吐最佳
llama.cpp CPU 与 Apple Silicon 推理;适合本地/边缘部署
Hugging Face TGI 部署简单;与 Hugging Face 模型库集成
DeepSpeed 训练与推理优化;张量并行;Microsoft

最佳实践

挑战 说明 建议
TTFT 过高 大输入的预填充耗时太长 使用提示词缓存;考虑长上下文优化的模型
TPOT 过高 解码太慢 投机解码;更小的模型;批量处理解码请求
内存 OOM 模型装不进 GPU 内存 量化到 W8 或 W4;使用张量并行;改用更小的模型
GPU 利用率低 尽管有负载,MFU 仍很差 启用连续批处理;增大批大小;排查碎片
成本过高 每 token 成本难以为继 将非延迟敏感负载批处理;使用缓存;尝试更小的模型
长序列性能退化 KV 缓存溢出 GQA/MQA 模型;滑动窗口;KV 缓存量化

参见

参考资料