交叉索引
五个层次
这门课按依赖关系排序,而不是按主题。每一层的存在,都是为了解决上一层制造出来的问题;真要动手写一个引擎,顺序也是这样。
1
模型本身
4 章 · 826 行把权重变成 token:分词器、Transformer 前向传播、采样。任何优化出现之前,这个循环就已经在了。
- S01生成循环自回归解码推理引擎就是一个把模型自己的输出再喂回去的 while 循环。这门课余下的全部内容,都是在优化这个循环。137 行
- S02分词从字节到 token id模型从来看不到文本。BPE 分词器把字节压缩进一个固定词表,你报出的每个延迟数字都以 token 计,而不是以字符计。232 行
- S03Transformer 前向传播RMSNorm、RoPE、GQA、SwiGLU现代 decoder block 只有七个操作。用 NumPy 老老实实写一遍,之后所有 kernel 优化就都有了对照的正确答案。251 行
- S04采样把 logits 变成一个 token采样器是引擎里最便宜的部分,却是用户感受最强烈的部分。temperature、top-k、top-p、min-p 和各种惩罚,全都是在对 logits 动手术。206 行
现在你有了一个正确、但每生成一个 token 都要重算全部历史的引擎。
2
显存与 KV 缓存
4 章 · 1003 行几乎所有推理优化本质上都是显存优化:缓存 KV、给它分页、共享、压缩。
- S05KV 缓存decode 为什么是显存带宽瓶颈没有缓存时,生成第 N 个 token 的代价是 O(N²);有了缓存则是 O(N)。瓶颈也随之从算力转移到显存带宽。205 行
- S06PagedAttention给 KV 缓存做虚拟内存为每个请求分配连续 KV 缓冲区,会因碎片浪费掉 60–80% 的 KV 缓存显存。把缓存分页成固定大小的 block,几乎能全部收回。283 行
- S07前缀缓存同一段 prompt 绝不算第二遍共享的 system prompt、few-shot 示例和多轮对话意味着:大多数 prefill token 之前已经算过了。给 block 做哈希,然后复用。263 行
- S08量化让每个权重和每条 KV 少占几个 bitdecode 速度取决于每个 token 搬运的字节数,位宽减半,延迟也几乎减半。剩下要决定的,是让误差落在哪里。252 行
引擎已经很快,稀缺的资源换成了显存,不再是算力。
3
批处理与调度
4 章 · 1059 行单个请求会浪费一整张 GPU。连续批处理、调度器、抢占和分块 prefill 让它保持满载。
- S09连续批处理迭代级调度静态批处理让所有请求都得等最慢的那一个。改成在每次前向之间进出请求,吞吐能提升数倍。244 行
- S10调度器队列、预算与抢占每一步调度器都要决定哪些请求能跑。公平性、延迟 SLO、显存不足后的恢复策略,都在这里。442 行
- S11分块 Prefill别让长 prompt 卡住所有 decode一次 32k token 的 prefill 会把排在它后面的所有 decode 堵上一秒。把 prefill 切成小块,混进 decode 批次里。190 行
- S12FlashAttention在线 softmax,不落 N² 矩阵注意力根本不需要把分数矩阵物化出来。分块加上滚动的最大值与求和,就把 O(N²) 的显存开销变成了 O(N)。183 行
一张 GPU 现在被大量并发请求填满,限制它的是 kernel 本身。
4
解码加速
4 章 · 863 行打破「一次前向只出一个 token」的规则,并约束模型被允许说出什么。
- S13算子融合与 CUDA Graph干掉 kernel 启动开销小 batch 时 GPU 是在等 CPU。融合算子、回放已捕获的 graph,能省掉每个 token 数百次的 kernel 启动。185 行
- S14投机解码一次前向吐出不止一个 token廉价的草稿模型先猜 k 个 token,大模型一次前向就能验证全部 k 个。拒绝采样保证输出分布可证明地完全一致。188 行
- S15结构化输出受语法约束的解码合法 JSON 不是一个 prompt 问题。把 schema 编译成状态机,然后把语法不允许的 logit 全部屏蔽掉。338 行
- S16专家混合(MoE)稀疏计算,稠密显存一个 MoE 层对每个 token 只激活 256 个专家中的 8 个。算力降了,显存没降,路由则变成了负载均衡问题。152 行
单机的余量已经被榨干。剩下的问题,一台机器装不下了。
5
分布式服务
4 章 · 1186 行把模型切分到多张 GPU,把 prefill 与 decode 拆到不同机器,再在前面加一层 API。
- S17张量并行与流水线并行一个模型,多张 GPU先按列切、再按行切每个 matmul,每个子层只需要一次 all-reduce。流水线并行则是用延迟换容量。216 行
- S18Prefill/Decode 分离部署两种负载,两组机器prefill 受算力约束,decode 受带宽约束。挤在同一张卡上,两个 SLO 都达不到;那就把它们拆开,再把 KV cache 传过去。186 行
- S19服务层OpenAI 兼容的流式 API用户看到的是 TTFT 和 token 间延迟,不是 FLOPs。API 层负责流式推送 SSE、处理取消,并导出你真正拿来调优的指标。363 行
- S20完整的引擎把所有零件接起来把前十九章的零件装成一个引擎:调度器、分页缓存、前缀复用、投机解码、流式服务器,最后跑一遍基准测试。421 行
现在你有了一个引擎。这个领域余下的工作,都是在细化上面这几步。
6
收官之作
2 章 · 4513 行拿一个真实的 2944 行 C 引擎,逐模块用 Python 重写一遍。全课程只有这一章的参考实现,是别人正在用的生产代码。
- S21用 Python 重写 picoLM一个真实的引擎,逐模块拆解picoLM 用 2944 行 C,在一块 10 美元、256 MB 内存的板子上跑起了 11 亿参数的模型。逐模块把它移植到 NumPy,这门课的每一章都能在里面找到,连它有意省掉的那两章也算在内。495 行
- S22用 TypeScript 写 mini-picoLM同一个引擎,就跑在这个标签页里把引擎第三次重建一遍:一个 ArrayBuffer、一个 arena、十八个步骤,做出一个不需要服务端、不需要 WASM、零依赖就能在浏览器里生成文本的引擎。JavaScript 里难的是内存,不是数学。4018 行
现在你能从头到尾读懂一个生产引擎了,因为你写过一个版本:它对的地方逐字节吻合,它错的地方不跟着错。
全部概念,以及它们在哪里被构建
只想找某一个具体机制、而不是读完一整章时,从这里进入。
- 前向传播S01
- 自回归S01
- logitsS01
- EOSS01
- prefill 与 decodeS01
- BPES02
- merge 规则S02
- 字节兜底S02
- 词表S02
- 流式解码S02
- RMSNormS03
- RoPES03
- 分组查询注意力S03
- SwiGLUS03
- 残差流S03
- temperatureS04
- top-kS04
- top-pS04
- min-pS04
- 重复惩罚S04
- 随机种子S04
- 缓存布局S05
- prefill/decode 分离S05
- 算术强度S05
- 带宽墙S05
- block tableS06
- 块管理器S06
- 内部碎片S06
- 写时复制S06
- gather kernelS06
- 块哈希S07
- 基数树S07
- LRU 淘汰S07
- 引用计数S07
- 缓存命中率S07
- INT8/INT4S08
- 分组 scaleS08
- GGUF K-quantS08
- AWQ/GPTQS08
- KV 缓存量化S08
- 静态 vs 连续S09
- 迭代级调度S09
- 不规则 batchS09
- 消除空泡S09
- 等待/运行队列S10
- token 预算S10
- 抢占S10
- 换出 vs 重算S10
- 准入控制S10
- token 间延迟毛刺S11
- chunk 大小调优S11
- 顺带执行S11
- TTFT/ITL 权衡S11
- 在线 softmaxS12
- 分块S12
- 重缩放S12
- IO 感知S12
- 分页版本S12
- 启动开销S13
- 算子融合S13
- graph 捕获S13
- 静态 shapeS13
- 分桶补齐S13
- 草稿模型S14
- n-gram 查找S14
- 验证S14
- 拒绝采样S14
- 接受率S14
- EAGLE/MedusaS14
- 有限状态机 / 下推自动机S15
- logit 掩码S15
- token 级语法S15
- 跳跃解码S15
- 路由器S16
- top-k 门控S16
- 专家分发S16
- token 分组S16
- 专家并行S16
- 按列/按行切分S17
- all-reduceS17
- 按头切分S17
- 流水线阶段S17
- micro-batchS17
- P/D 拆分S18
- KV 传输S18
- NIXL/RDMAS18
- SLO 达标S18
- 实例配比调优S18
- SSE 流式输出S19
- 对话模板S19
- 请求取消S19
- TTFT/ITL/TPOTS19
- 负载均衡S19
- 引擎核心S20
- 端到端串联S20
- 基准测试S20
- 消融实验S20
- 接下来做什么S20
- GGUF 与 mmapS21
- K-quantS21
- 融合反量化S21
- SentencePiece BPES21
- 语法掩码S21
- 移植S21
- ArrayBuffer 与 arenaS22
- 类型化数组视图S22
- 融合量化 matmulS22
- 异步生成S22
- WebGPUS22
- 交付到标签页S22