📑 本页目录(点开跳转)
06 · 推理优化:让它跑得快、跑得起
⏱ 40 分钟 | ⭐⭐ 自建部署的核心,也是省钱最大的杠杆
🎯 一句话
推理优化解决一个矛盾:模型很大,显存很贵,用户很急。三大武器是量化(压小)、批处理(吞吐)、投机解码(降延迟)。
🧠 先理解瓶颈在哪:两个阶段
① Prefill(预填充)—— 处理你的输入提示词
所有 token 可以并行算 → 计算密集(GPU 算力吃满)
时间 ∝ 输入长度
决定了「首字延迟 TTFT」
② Decode(解码)—— 一个一个吐出回答
每次只算 1 个 token,但要把整个模型权重从显存搬到计算单元
→ 访存密集(显存带宽吃满,算力大量闲置!)⭐
决定了「每字延迟 TPOT」
🔑 最反直觉也最重要的一条: Decode 阶段的瓶颈是显存带宽,不是算力。 GPU 的算力大部分时间在空转,卡在「把 14GB 权重搬过来」这件事上。
这一条解释了后面所有优化的底层逻辑。
💡 顺带把一件事说清楚:Decode 每一步吐出来的其实是一个概率分布,不是一个词。
从分布里挑出那一个词的规则叫解码策略——你天天在调的 temperature / top_p 就在那一步。
它和"跑得快"是两件正交的事,所以单独成章:06b · 解码策略。
这一章只管速度和成本,看到"输出飘/复读"这类问题就该去那一章。
🗜️ 武器一:量化(Quantization)
思路:权重本来用 16 位浮点存,改成 8 位甚至 4 位整数。
FP16 (16bit) → INT8 (8bit) → INT4 (4bit)
显存 100% 50% 25%
7B 模型:14GB → 7GB → 3.5GB (消费级显卡能跑了!)
70B 模型:140GB → 70GB → 35GB (单卡 A100 能跑)
为什么还能用:神经网络对权重精度有惊人的容忍度。4bit 量化后,多数任务的效果损失在 1–3%。
主流方案速查:
| 方案 | 特点 | 场景 |
|---|---|---|
| GGUF(llama.cpp) | CPU/GPU 混合、格式通用 | 本地跑、Mac、消费级设备 ⭐ |
| AWQ | 激活感知,保护重要权重 | GPU 服务,质量好 |
| GPTQ | 逐层校准量化 | GPU 服务,经典方案 |
| FP8 | 新硬件原生支持 | H100 及以后的卡 |
⚠️ 注意:量化省的是显存和带宽(因此 decode 变快),不一定省计算。而且 KV Cache 也可以单独量化——长上下文时这个收益很大。
⚠️ 量化的三个真实代价(别只看省显存)
| 代价 | 说明 |
|---|---|
| 长尾能力先崩 ⭐ | 平均分只掉 1-3%,但复杂推理、多语言、长上下文这些"边缘能力"掉得更多 |
| 量化后必须重测 | 别信"官方说损失很小"——用你自己的评测集测一遍(第 11 章) |
| 不同任务敏感度差很多 | 分类/抽取类几乎无损;数学、代码、多步推理最敏感 |
🔑 一条实用的选择规则: 显存刚好够 → 别量化;差一点点 → INT8;差很多 → INT4。 量化是"为了能跑"的妥协,不是"免费的优化"。
🧮 显存怎么估(部署前先算这一笔)
总显存 ≈ 模型权重 + KV Cache + 激活/框架开销
模型权重 = 参数量 × 每参数字节数
FP16 = 2 字节,INT8 = 1,INT4 = 0.5
7B FP16 → 14GB;7B INT4 → 3.5GB
KV Cache = 2 × 层数 × KV头数 × 头维度 × 序列长 × batch × 精度字节
(第 2 章算过:70B 模型每 token 约 2.6MB)
开销 ≈ 权重的 10~20%
⭐ 最常见的翻车:只算了权重,没算 KV Cache
→ "3.5GB 的模型怎么在 8GB 卡上 OOM 了"
📦 武器二:批处理(提升吞吐)
既然 decode 卡在「搬权重」,那就搬一次权重,同时给多个用户算——这是吞吐提升的关键。
❌ 静态批处理:等 8 个请求凑齐一起跑
问题:有的请求 10 字就答完,有的要 1000 字
短的必须干等长的,GPU 大量空转
✅ 连续批处理 (Continuous Batching) ⭐ vLLM 的核心
谁答完谁下车,新请求立刻上车
→ 吞吐提升 几倍到 10 倍以上
PagedAttention:借鉴操作系统的虚拟内存
问题:KV Cache 要预留最大长度的显存,但实际用不了那么多
→ 大量显存浪费(碎片化),能同时服务的用户数被限制
解法:像操作系统管理内存页一样,把 KV Cache 切成小块按需分配
→ 显存利用率大幅提升 → 能塞下更多并发用户
📌 这是 vLLM 成为事实标准的原因。同样的卡,吞吐能翻好几倍。
⚡ 武器三:投机解码(降低延迟)
常规:大模型一次吐 1 个 token,每次都要搬 140GB 权重
投机解码:
① 让一个小模型(草稿模型)快速猜 5 个 token
② 大模型一次性并行验证这 5 个 ← 关键:验证和生成 1 个的成本差不多!
(因为瓶颈是搬权重,不是算力)
③ 猜对的部分直接采纳,第一个猜错的地方开始重来
→ 猜中率高时,延迟降低 2–3 倍,且输出分布严格等价 ✅
💡 为什么能白赚:正因为 decode 是访存密集的,GPU 算力本来就在空转——并行验证 5 个 token 几乎不额外花时间。
变体:Medusa(多头并行预测)、EAGLE、n-gram 查表(无需额外模型)。
🎲 三大武器管的都是「这一步跑得多快」——但还有一半不在这一章。 Decode 每一步吐出来的其实是一个概率分布,「从分布里挑哪个词」是完全另一套东西:
temperature、top_p、那几个 penalty 全住在那里,和速度优化正交。 两章的分工看现象就能分清:慢、贵、显存不够 → 留在这一章; 输出飘、复读、每次结果不一样、JSON 间歇性打不开 → 去 06b · 解码策略。 ⚠️ 顺带说,两章有一个真实的交集:T=0 也不保证逐位复现——归约顺序会随 batch 组成变化, 而动态 batch 正是上面武器二连续批处理造成的。吞吐优化和逐位复现是一对天然矛盾,那条在 06b 讲透。
🧰 其他常用手段
| 手段 | 作用 |
|---|---|
| GQA/MQA | 多个 Q 头共享 K/V 头 → KV Cache 省好几倍(第 2 章提过) |
| Prefix Caching | 相同的系统提示词只算一次,多请求复用 ⭐ 省钱利器 |
| FlashAttention | 减少显存读写,长上下文提速明显 |
| 张量并行 | 一个模型切到多张卡上(放不下时的必选) |
| 算子融合 / CUDA Graph | 减少 kernel 启动开销 |
💰 Prefix Caching 对做 Agent 的人特别重要:Agent 每轮都重发完整历史(智能体教程第 1 章), 前缀完全相同——缓存后能省掉绝大部分 prefill 成本。这也是为什么「稳定内容放前面、动态内容放后面」是条金规则。
🚨 Prefix Caching 的杀手:三个会让命中率归零的写法
❌ 系统提示词开头放当前时间 → 每次前缀都不同,命中率 0%
❌ 每次动态排序工具列表 → 顺序一变前缀就变
❌ 把用户 ID / 会话 ID 放最前面 → 每个用户各自一份缓存,等于没缓存
✅ 正确布局:
[固定的系统提示词]
[固定的工具定义]
[很少变的背景资料]
───────── 缓存边界大致在这里 ─────────
[会话历史]
[当前时间、用户信息等动态内容]
[用户问题]
🔑 一句话:前缀一个字符变了,从那里往后的缓存全部失效。 这是最容易犯、代价最大、也最容易修的一个错——改一下顺序就能省掉大半账单。
🎯 三个指标,别只盯一个
TTFT(首字延迟) ← 用户感知"它反应快不快"
TPOT(每字延迟) ← 用户感知"它打字快不快"
吞吐(总 token/秒) ← 你感知"这张卡能服务多少人"
⚠️ 它们互相冲突:
· 加大 batch → 吞吐↑ 但 TTFT 和 TPOT ↓(要排队)
· 减小 batch → 延迟↓ 但吞吐↓(卡在空转)
| 你的场景 | 该优先什么 |
|---|---|
| 对话产品(有人在等) | TTFT ⭐ ——首字出来得快,用户就觉得快 |
| Agent / 批处理任务 | 吞吐 ——没人盯着,把卡榨满 |
| 代码补全 | TPOT ——要跟得上打字速度 |
💡 一个便宜的心理学优化:开流式输出。 总时长没变,但用户看到字在动,感知延迟大幅下降—— 这往往比任何推理优化都划算。
🔗 和你已知的关系
左列有的来自日常用 LLM 的经验,有的在站内别的板块讲过——碰上过哪几条就从哪几条接进来,一条没碰过也不影响读这一章。
| 你可能已经知道的 | 这一章的「为什么」 |
|---|---|
| 提示缓存能省钱(智能体第 12 章) | 就是 Prefix Caching,原理在这 |
| 稳定内容放前、动态放后 | 前缀相同才能命中缓存 |
| 长上下文贵 | Prefill 计算 + KV Cache 显存双重成本 |
| 小模型执行、大模型把关(第 2 章顾问策略) | 投机解码是它的"硬件版本" |
| 流式输出一个字一个字 | Decode 阶段的本质 |
想接着深挖,去这几处:
| 去哪 | 为什么 |
|---|---|
| AI基础设施 18 | 武器一的展开:为什么掉点、离群值是根因、什么时候别量化 ⭐ |
| AI基础设施 17 | 武器二的展开:块表、写时复制、抢占,以及连续批处理和静态批处理的差别 |
| AI基础设施 19 | 武器三的展开:接受-拒绝规则、加速比公式、什么场景白赚 |
| 06b · 解码策略 | ⭐ 这一章的另一半:同样是 decode 那一步,但管的是选哪个词——temperature / top_p / 复读惩罚怎么配、为什么 T=0 也不保证逐位复现 |
| 上线之后 18 | ⭐ 省下来的算力怎么换算成容量:排队、超时、雪崩 |
📦 深挖的话要学什么
📍 每条后面标了它在哪: 📗 本库有 = 站内已经讲透,点进去就行;📙 半有 = 站内讲了一半,另一半得外找; 📕 要外找 = 站内没有,得去论文或别处。 (这份清单以前只列词不说去哪,指到的坑有些站内根本没挖过,按图索骥会扑空。) ⭐ 这一章是全导论「本库有」比例最高的一章——《AI基础设施》基本是它的完整展开版。
- 原理:Roofline 模型(算力 vs 带宽瓶颈分析)、算术强度 → 📗 本库有:AI基础设施 04 · Roofline与MFU + 03 · 显存与带宽墙。本章开头"Prefill 受算力限制、Decode 受带宽限制"是结论,Roofline 是那个能让你自己算出来的工具——知道算术强度怎么算,你就能在买卡之前判断某个负载到底卡在哪一边
- 量化:对称/非对称、per-tensor/per-channel/per-group、GPTQ 与 AWQ 的算法差异、KV Cache 量化、量化感知训练 → 📗 本库有,整条都有:AI基础设施 18 · 量化——离群值为什么是 LLM 量化的核心难题、per-group(每 128 个权重一组)为什么成了主流、AWQ 的"只有 1% 的权重重要"、GPTQ、KV Cache 量化,以及 PTQ vs QAT(⭐ 结论是 LLM 时代 PTQ 一边倒,因为 QAT 要重训,70B 重训一遍的成本和"掉的那 1 分"完全不成比例——所以这一项你多半不会用到,但值得知道为什么不用)
- 服务框架:vLLM / SGLang / TensorRT-LLM / TGI 的架构与选型 → 📗 本库有:AI基础设施 20 · 推理服务化 的七引擎横评 + 四问决策树,TGI 也在里面(它属于"生态贴合"型选择——不是更快,是你已经在 HF 那套里了)。⚠️ 去之前先记住那一章最反直觉的一条:引擎之间通常只差 20–50%,而配置有没有调对差的是几倍——大部分"快 3 倍"的评测拆开看都是一边开了连续批处理一边没开。先调配置,再换引擎
- 调度:连续批处理、PagedAttention、分块预填充(chunked prefill)、prefill/decode 分离部署 → 📗 本库有:AI基础设施 17 · 连续批处理与PagedAttention 四项全覆盖,还多给了一笔本章没有的账——P/D 分离不是免费午餐:分开之后 KV 要跨机搬,而 InfiniBand 带宽只有 HBM 的约 1/60
- 投机解码:草稿模型选择、接受率优化、Medusa/EAGLE → 📗 本库有:AI基础设施 19 · 投机解码。本章「武器三」讲了它为什么有效,那一章讲的是怎么让它真的有效:加速比由接受率 α 和草稿成本 c 两个变量决定(c 通常要 ≤1/10 才划算;代码任务因为模式可预测,α 能到 0.85 以上),Medusa(加预测头,草稿成本近零但猜得糙)和 EAGLE(把自回归挪到特征层换接受率)各自的位置
- 性能工程:压测方法、TTFT/TPOT/吞吐三角权衡、成本建模 → 📗 本库有:AI基础设施 20 · 推理服务化 的「先定 SLO 再谈优化」和「压测:画出你的延迟-吞吐曲线」,成本那一侧在 AI基础设施 23 · 可观测性与成本。本章的"三个指标别只盯一个"到这里变成可执行的流程
- 实操:用 vLLM 部署一个模型,做一次完整压测
→ 📙 半有:该开哪些参数、压测该画什么曲线、上线检查清单,AI基础设施 17 和 20 都给了(含
enable_chunked_prefill/enable_prefix_caching/kv_cache_dtype这几个具体开关);AI基础设施 24 · 实战与挑战项目 有对应的动手项目。但"从零装一台机器跑起来"这段环境搭建站内没有,要外找(vLLM 官方 quickstart)
需要的前置:第 2 章 Transformer + Linux/GPU 基础。不需要深厚数学。
⚖️ 要不要深挖
| 你的情况 | 建议 |
|---|---|
| 只用 API,量不大 | ⛔ 不用。知道 Prefix Caching 会用就行 |
| API 账单开始肉疼 | 🟡 先做提示词优化和缓存,再考虑自建 |
| 数据不能出内网 / 有合规要求 | ✅ 必须,配合第 7 章 |
| 有稳定的大流量,自建更划算 | ✅ 必须,这块直接省真金白银 |
| 做 AI 基础设施 / 平台岗 | ✅ 核心技能 |
🔑 我的判断:这块工程性极强、几乎不涉及数学,对有后端背景的人上手很快。 价值判断很简单:看你的账单。如果每月 API 花费还不够租一张 GPU,就别折腾自建。 但「Prefix Caching + 提示词结构优化」是所有人现在就该做的,本章内容已经够。
✅ 检查点
- Prefill 和 Decode 各自的瓶颈是什么?为什么这个区别重要?
- 4bit 量化把 70B 模型从多少压到多少?主要省的是什么?
- 量化的三个真实代价是什么?什么任务对量化最敏感?选择规则是什么?
- 估部署显存时最容易漏掉什么?
- 连续批处理比静态批处理好在哪?
- 投机解码为什么能「白赚」速度?
- Prefix Caching 对 Agent 场景为什么特别有价值?哪三个写法会让命中率归零?
- TTFT / TPOT / 吞吐三个指标怎么冲突?对话产品该优先哪个?
- 最便宜的"延迟优化"是什么?
👀 答案
- Prefill 计算密集(并行处理输入,决定首字延迟);Decode 访存密集(每次搬整个模型权重只算 1 个 token,决定每字延迟)。重要是因为 Decode 卡在显存带宽而非算力,这是所有优化的底层逻辑。
- 140GB → 35GB。主要省显存和带宽(因此 decode 变快),不一定省计算。
- ①长尾能力先崩(平均只掉 1-3%,但复杂推理/多语言/长上下文掉更多)②必须用自己的评测集重测 ③不同任务敏感度差很多——数学、代码、多步推理最敏感。规则:显存刚好够就别量化,差一点用 INT8,差很多才 INT4——量化是妥协不是免费优化。
- KV Cache。最常见的翻车是"3.5GB 的模型怎么在 8GB 卡上 OOM 了"——只算了权重没算 Cache 和框架开销。
- 静态批处理要等最长的请求结束,短请求占着位置空转;连续批处理谁答完谁下车、新请求立刻补位,吞吐提升数倍。
- 因为 decode 是访存密集的,GPU 算力在空转——大模型并行验证 5 个 token 和生成 1 个的耗时几乎相同,所以猜中的部分等于白赚。
- Agent 每轮重发完整历史,前缀完全相同,缓存后省掉绝大部分 prefill 成本。三个归零写法:①系统提示词开头放当前时间 ②每次动态排序工具列表 ③把用户 ID/会话 ID 放最前面。前缀一个字符变了,从那往后全部失效。
- 加大 batch → 吞吐↑ 但延迟↓;减小 batch → 延迟↓ 但吞吐↓。对话产品该优先 TTFT——首字出来得快用户就觉得快。
- 开流式输出。总时长没变,但用户看到字在动,感知延迟大幅下降——往往比任何推理优化都划算。
🛑 可以停在这里
⚡ 走神救援
核心认知:Decode阶段瓶颈是显存带宽不是算力,这解释了所有优化。三武器:①量化(FP16→INT4,显存降75%,GGUF本地/AWQ服务)——⚠️三个真实代价:长尾能力先崩(平均只掉1-3%但复杂推理/多语言掉更多)、必须用自己的评测集重测、数学和代码最敏感;规则"显存刚好够就别量化",它是妥协不是免费优化 ②连续批处理+PagedAttention(vLLM核心,吞吐翻数倍) ③投机解码(小模型猜5个大模型并行验,白赚2-3倍,因为算力本来就在空转)。还有GQA省KVCache、Prefix Caching省prefill(Agent场景金矿)——⚠️三个让命中率归零的写法:开头放当前时间、动态排序工具列表、用户ID放最前面;前缀一个字符变了从那往后全失效,改个顺序就能省掉大半账单。⚠️估显存最容易漏掉KV Cache("3.5GB模型怎么在8GB卡上OOM")。三指标冲突:加大batch吞吐↑但延迟↓;对话产品优先TTFT、Agent优先吞吐、代码补全优先TPOT。⭐最便宜的优化是开流式输出——总时长没变但感知延迟大降。判断标准:看账单,但Prefix Caching所有人现在就该用。⚠️这一章只管"跑多快";decode那一步"选哪个词"(temperature/top_p/复读惩罚)是正交的另一半,在 06b 解码策略——慢和贵查这一章,输出飘/复读/JSON间歇打不开查那一章。
下一节 👉 06b-解码策略.md