深言速舟 · 学习站

第一部分:先建立物理直觉

LLM 推理加速:从 0 到 1 教学手册第一部分:先建立物理直觉约 10 分钟更新于 2026-08-05

1.1 GPU 为什么"慢"

听起来奇怪 —— GPU 不是很快吗?为什么说它慢?

GPU 的算力(计算速度)很快,但显存到计算单元的数据搬运速度,慢得多。

打个比方:

  • GPU 计算单元 = 一个超人,1 秒能做 1000 万亿次乘法
  • GPU 显存 = 超人旁边的仓库,里面装着模型权重(要计算的"原料")
  • 传送带 = HBM 带宽,把原料从仓库送到超人手上

关键事实:超人干活的速度,是传送带送货速度的几百倍到一千倍。

意思是:如果超人手边的原料没了,他就得停下来等传送带。等的时间里,超人闲着。

H800 的具体数字:

指标 数值 物理含义
FP16 算力 ~1000 TFLOPS 每秒 1000 万亿次乘法
FP8 算力 ~2000 TFLOPS FP8 翻倍
HBM 显存大小 80 GB 显存仓库
HBM 带宽 ~3 TB/s 仓库到计算单元的传送带
NVLink(H800) 400 GB/s 同机内卡和卡之间
PCIe 5.0 64 GB/s GPU ↔ CPU

关键比例:算力 ≈ HBM 带宽 × 300 倍。

所有推理加速技术,本质上都在解决同一个问题:要么减少传送带要送的货,要么让超人在等货的时候顺便干点别的,要么让传送带送货更聪明。

1.2 模型在 GPU 里长什么样

模型权重 = 一堆数字(参数)。

脱敏说明:本稿件逐类检查九类敏感项,未发现需要替换的内容。文中出现的 H800 为公开销售的硬件型号,其 HBM 带宽、FP8 算力等参数均为公开产品规格,非内部部署信息,故保留。原稿第 8 页之后(1.2 节起至附录)未包含在本稿件输入中,如需完整内容请获取原稿。

一个 70B(700 亿参数)模型,每个参数用 2 字节存(FP16 精度),共 140 GB。 某型号卡单卡只有 80GB 显存,装不下 140 GB。所以你只有三个选择: 压缩模型(量化):每个参数用 1 字节存,模型变成 70 GB,能装进单卡 切到多卡:把模型分到 2 张卡上,每张卡装一半 换更小的模型 这就是为什么后面会反复看到"FP8 量化"和"多卡部署"。

1.3 LLM 是怎么"说话"的(自回归生成)

你必须先扔掉一个错误直觉

❌ 错误直觉:你问一句话,模型读懂,然后输出一整段回答。 ✅ 实际真相:模型只能预测"下一个字"。一整段回答是一个字一个字蹦出来的。

用例子讲清楚

你问:"请帮我写一首关于杭州的诗" 模型的回答:"江南忆,最忆是杭州"

这 9 个字是怎么生成的?模型不知道自己接下来要说"江南忆"。它每一步只做一件事:看看目前已有的文字,预测下一个字应该是什么。

第1步: 已知 = "请帮我写一首关于杭州的诗" 模型预测下一个字 = "江"

第2步: 已知 = "请帮我写一首关于杭州的诗江" ← 把"江"加进来 模型预测下一个字 = "南"

第3步: 已知 = "请帮我写一首关于杭州的诗江南" 模型预测下一个字 = "忆"

...一直循环,直到模型预测出"<结束>"标记

每一步,整个 140 GB 模型权重都要从显存搬到计算单元走一遍。

这种"一个字一个字往外蹦"的方式,叫自回归生成(Auto-regressive Generation)。ChatGPT 网页上你看到的"流式输出",就是模型真实的工作方式。

1.4 推理的两个阶段:Prefill 和 Decode

理解了自回归,现在能讲清楚推理的两个阶段了。

Prefill = 处理你的输入,吐出第一个字

输入:"请帮我写一首关于杭州的诗"(10 个字) Prefill 做的事:把这 10 个字一起喂给模型,让模型预测出第一个回答字"江"。

关键点:因为这 10 个字都是已知的,可以同时塞进 GPU 让所有计算单元一起算。

矩阵规模大 → 超人忙得过来 → GPU 算力利用率 60-80% 这叫 compute-bound(算力是瓶颈) 时间:100-200 毫秒

Decode = 一个字一个字往外蹦

第一个字"江"已经有了。现在要生成"南"、"忆"...

Decode 做的事:每次只把 1 个新字喂给模型,预测下一个字。

关键点:因为下一个字必须等当前字生成完才知道,没法并行,只能一次一个。但是 —— 整个 140 GB 模型权重还是要搬运一遍。

矩阵规模小 → 超人只算 1 个字 → 但搬运量没变 → GPU 算力利用率 1-5% 这叫 memory-bound(搬运是瓶颈) 时间:每个字 10-30 毫秒。500 个字 = 5-15 秒

两个阶段的对比

Prefill Decode
做什么 处理用户输入,吐第一个字 循环生成后续每个字
一次处理多少字 10-1000 个(用户全部输入) 1 个
能不能并行 可以(输入已知) 不能(必须串行)
GPU 利用率 60-80% 1-5%
瓶颈 算力 (compute-bound) 搬运 (memory-bound)
用时(典型请求) 100-200ms 5-15 秒

整个推理领域的"原罪"

一个典型请求:Prefill 100-200 ms,Decode 5-15 秒。

95% 以上的时间花在 Decode 阶段,而 Decode 阶段 GPU 算力闲着 95%。

整个推理加速领域所有技术,都在解决一个问题:怎么把 Decode 阶段那 95% 闲置的算力用起来。

三个最常见的误解,必须校正

误解 1: "Prefill 已经喂给模型了,为什么还要 Decode" 校正:Prefill 只处理了用户的输入 prompt,只产出了第一个回答 token。后面所有的回答 token 都要靠 Decode 循环生成。 类比:你问朋友一个问题。 Prefill = 朋友"听明白你的问题",并说出第一个字"我" Decode = 朋友继续说"觉得...这件事...应该...这样..."一个字一个字往外蹦

误解 2: 模型一次性输出整段回答 校正:LLM 根本不知道自己接下来要说什么。它每次只能预测"下一个 token 的概率分布"。

误解 3: 觉得 Decode 是"在解码 Prefill 的结果" 校正:"Decode" 这个词翻译得不好。Decode 和 Prefill 做的是同一件事 —— 都是"过一遍模型,预测下一个 token"。区别只在于: Prefill: 一次同时处理多个 input token(并行处理已知的 prompt) Decode: 一次只处理 1 个新生成的 token(自回归约束)

1.5 KV Cache:让自回归能跑起来的关键

到这里你可能会问:生成第 500 个字的时候,模型怎么"记得"前面 499 个字是什么?

答案是 Attention 机制 —— 每生成一个新字,模型会"回头看"前面所有字,决定新字应该是什么。

问题:朴素做法太贵

如果每生成一个字都重新"回头看"前面所有字: 生成第 1 个字:算 1 个字 生成第 500 个字:重算前面 499 个字

总成本是 N² 量级的,N=500 时比"只算一次"贵 250 倍

这种成本下,ChatGPT 根本不可能存在。

解决:KV Cache

道理很简单:算过的东西,存下来,下次直接用。

具体来说,每个字会被模型算出两个东西: K (Key) = 这个字的"特征标签" V (Value) = 这个字的"内容信息"

每生成一个新字时,模型只需要算新字的 K 和 V,然后从 cache 里读出所有历史字的 K 和 V,做一次 attention。

复杂度从 O(N²) 降到 O(N)。这才让自回归生成在工程上可行。

代价:KV Cache 很占显存

每个字的 K/V 大约 320 KB。一个长对话的 KV Cache 可以占几十 GB。

场景 KV Cache 占用
70B 模型,2K 上下文 ~0.6 GB
70B 模型,32K 上下文 ~10 GB
70B 模型,128K 上下文 ~40 GB

KV Cache 是后面所有显存优化技术的核心战场。PagedAttention、Prefix Caching、KV 量化、KV Offloading —— 全都在围绕 KV Cache 做文章。

1.6 Token 是什么

到现在为止我一直说"字"。实际上模型处理的最小单位不是字,是 token。

Token 不等于字或词

输入 Token 数 怎么切的
Hello 1 ["Hello"]
Hello, world! 4 ["Hello", ",", " world", "!"]
unbelievable 2 ["unbel", "ievable"]
你好 2 ["你", "好"]
推理加速 4 ["推", "理", "加", "速"]

粗略规律: 英文:1 个 token ≈ 0.75 个单词 中文:1 个 token ≈ 1.5 个汉字

一个关键的商业事实:中文 token 效率低

同样一段话表达同样的意思,中文消耗的 token 比英文多 30-50%。

为什么?分词算法(BPE)基于训练语料统计,训练语料以英文为主,所以英文有大量"高频词组合"被合并成单个 token,中文大部分还是一字一 token。

对某 MaaS 平台的商业含义:如果按 OpenAI 的英文 token 定价标杆收费,中文客户实际可能是亏的(token 账单数字大,但 GPU 时间也多,毛利率低)。定价模型应该考虑中英文差异。

Input vs Output Token

Input Token = 用户输入的 token 数(被 Prefill 阶段处理) Output Token = 模型生成的 token 数(被 Decode 阶段生成)

Output Token 通常比 Input 贵 2-4 倍。原因你现在已经懂了:Input 走 Prefill,GPU 效率 60-80%,便宜;Output 走 Decode,GPU 效率 1-5%,贵。OpenAI、Anthropic、阿里都这样定价。

第一部分小结

你应该能用一句话回答下面这些问题:

Q: LLM 为什么慢? A: 因为大部分时间花在 Decode 阶段,Decode 是一个字一个字串行生成,每生成一个字都要把整个模型权重搬运一遍。GPU 算力实际只用了 1-5%。

Q: 为什么要 KV Cache? A: 因为生成每个新字都要"回头看"前面所有字,没有缓存的话计算量是 N²。KV Cache 让历史字的特征算一次就缓存下来。

Q: 显存为什么总不够? A: 模型权重占大头(70B FP16 就是 140 GB),KV Cache 是另一个大头,且按对话长度增长。

Q: 为什么 Output 比 Input 贵? A: 输入走 Prefill 阶段 GPU 效率高,输出走 Decode 阶段 GPU 效率低、成本高。

修订记录

日期改了什么为什么谁
2026-08-05从整篇拆成第 2/6 章,正文未改动整篇 44 分钟读不完,拆成每章 20 分钟以内工程