跳到正文
LLM 推理

22 章 · 9,450 行代码 · 不需要 GPU

从零构建LLM 推理引擎的全过程。

调用推理 API 谁都会,难的是说清楚 vLLM 为什么能比一段简短的 PyTorch 循环快 40 倍。本课程要补的就是这段落差:从最朴素的生成循环出发,一次消除一个瓶颈。

每章配一张机制图、一个可以自己上手调的模拟器、六道带解析的习题,还有一个能直接运行、并回头验证本章结论的文件。

$ pip install numpy && python code/s01_generation_loop.py

第 1 章 · 整个引擎

一次迭代 = 一个 TOKENprompt"The cat"tokenizer文本 → id前向传播L × decoder blocklogits[vocab_size]采样器argmax / top-ptoken"sat"追加到上下文 —— 下一次前向就多看到一个 token若为 EOS解码 + 输出id → 文本3 次迭代后的上下文Thecatsatonthemat灰色 = prompt(一次性并行算完 —— 即 prefill)橙色 = 生成的(每次前向出一个 —— 即 decode)每一次前向都要重读整个上下文。这正是 S05 要消除的开销。

01

先写出循环,再逐一消除瓶颈。

引擎调用模型、采样一个 token、把它追加到序列,然后重复。后续章节要处理的,就是这个短循环藏起来的东西:重复计算、硬件空闲,以及迟早会耗尽的显存。

02

几乎所有优化都是显存优化。

decode 要读完整个模型才产出一个 token,瓶颈在于搬运的字节数,而非算术运算。KV 缓存、分页、前缀复用和量化都由此而来,它们也占了本课程的大半篇幅。

03

逐步建立阅读生产级引擎的能力。

每章都把核心概念落到 vLLM、SGLang、llama.cpp、picoLM 或 quant.cpp 上,读完总有一份具体的源码可以接着打开。

课程结构

五个层次,二十章,外加两章收官

每一层都建立在上一层引出的约束之上。第一遍建议按顺序读;顺序一乱,技术之间的依赖关系就看不出来了。

模型本身

S01S04

把权重变成 token:分词器、Transformer 前向传播、采样。任何优化出现之前,这个循环就已经在了。

……于是循环正确了,却慢到不能用。所以:

显存与 KV 缓存

S05S08

几乎所有推理优化本质上都是显存优化:缓存 KV、给它分页、共享、压缩。

……于是稀缺资源变成了显存,而不是算力。所以:

批处理与调度

S09S12

单个请求会浪费一整张 GPU。连续批处理、调度器、抢占和分块 prefill 让它保持满载。

……于是一张 GPU 被大量请求填满了。所以:

解码加速

S13S16

打破「一次前向只出一个 token」的规则,并约束模型被允许说出什么。

……于是单机能给的都榨干了。所以:

分布式服务

S17S20

把模型切分到多张 GPU,把 prefill 与 decode 拆到不同机器,再在前面加一层 API。

收官之作

S21S22

拿一个真实的 2944 行 C 引擎,逐模块用 Python 重写一遍。全课程只有这一章的参考实现,是别人正在用的生产代码。

每一章都有

一张机制图

沿着真实的数据流,观察计算、内存传输与延迟分别在何处产生。

一个交互式模拟器

把输入推到边界情况出现为止:耗尽 KV 池,挪动采样阈值,然后看系统怎么应对。

一组带解析的习题

每章六道判分题,每道题都配有解析,并指向需要复习的核心概念。

一个能跑的文件

自包含,只依赖 NumPy;TypeScript 收官章除外,它用 Node 运行。文件会断言自己的结论,两秒内跑完。不用下载模型,不用 PyTorch,也不需要 GPU。

从生成循环开始。

第 1 章是九行 Python 和一次令人不适的测量。后面的全部内容,都从这次测量推出来。

S01 · 生成循环 →