🏠 总目录📚 本教程 06 · 推理优化
📑 本页目录(点开跳转)

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 每一步吐出来的其实是一个概率分布,「从分布里挑哪个词」是完全另一套东西: temperaturetop_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基础设施》基本是它的完整展开版。

需要的前置:第 2 章 Transformer + Linux/GPU 基础。不需要深厚数学。


⚖️ 要不要深挖

你的情况 建议
只用 API,量不大 ⛔ 不用。知道 Prefix Caching 会用就行
API 账单开始肉疼 🟡 先做提示词优化和缓存,再考虑自建
数据不能出内网 / 有合规要求 必须,配合第 7 章
有稳定的大流量,自建更划算 必须,这块直接省真金白银
做 AI 基础设施 / 平台岗 ✅ 核心技能

🔑 我的判断:这块工程性极强、几乎不涉及数学,对有后端背景的人上手很快。 价值判断很简单:看你的账单。如果每月 API 花费还不够租一张 GPU,就别折腾自建。 但「Prefix Caching + 提示词结构优化」是所有人现在就该做的,本章内容已经够。


✅ 检查点

  1. Prefill 和 Decode 各自的瓶颈是什么?为什么这个区别重要?
  2. 4bit 量化把 70B 模型从多少压到多少?主要省的是什么?
  3. 量化的三个真实代价是什么?什么任务对量化最敏感?选择规则是什么?
  4. 估部署显存时最容易漏掉什么?
  5. 连续批处理比静态批处理好在哪?
  6. 投机解码为什么能「白赚」速度?
  7. Prefix Caching 对 Agent 场景为什么特别有价值?哪三个写法会让命中率归零?
  8. TTFT / TPOT / 吞吐三个指标怎么冲突?对话产品该优先哪个?
  9. 最便宜的"延迟优化"是什么?
👀 答案
  1. Prefill 计算密集(并行处理输入,决定首字延迟);Decode 访存密集(每次搬整个模型权重只算 1 个 token,决定每字延迟)。重要是因为 Decode 卡在显存带宽而非算力,这是所有优化的底层逻辑。
  2. 140GB → 35GB。主要省显存和带宽(因此 decode 变快),不一定省计算。
  3. 长尾能力先崩(平均只掉 1-3%,但复杂推理/多语言/长上下文掉更多)②必须用自己的评测集重测 ③不同任务敏感度差很多——数学、代码、多步推理最敏感。规则:显存刚好够就别量化,差一点用 INT8,差很多才 INT4——量化是妥协不是免费优化。
  4. KV Cache。最常见的翻车是"3.5GB 的模型怎么在 8GB 卡上 OOM 了"——只算了权重没算 Cache 和框架开销。
  5. 静态批处理要等最长的请求结束,短请求占着位置空转;连续批处理谁答完谁下车、新请求立刻补位,吞吐提升数倍。
  6. 因为 decode 是访存密集的,GPU 算力在空转——大模型并行验证 5 个 token 和生成 1 个的耗时几乎相同,所以猜中的部分等于白赚。
  7. Agent 每轮重发完整历史,前缀完全相同,缓存后省掉绝大部分 prefill 成本。三个归零写法:①系统提示词开头放当前时间 ②每次动态排序工具列表 ③把用户 ID/会话 ID 放最前面。前缀一个字符变了,从那往后全部失效。
  8. 加大 batch → 吞吐↑ 但延迟↓;减小 batch → 延迟↓ 但吞吐↓。对话产品该优先 TTFT——首字出来得快用户就觉得快。
  9. 开流式输出。总时长没变,但用户看到字在动,感知延迟大幅下降——往往比任何推理优化都划算。

🛑 可以停在这里

走神救援

核心认知: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

打卡记录保存在你的浏览器里,首页能看到总进度