home/tutorial/00 心智模型

心智模型

15 分钟建立全局观 — 在写任何代码之前。

这页只回答三个问题:"AI infra" 到底指什么?为什么 vLLM 是好的入口?为什么 OS 是它的母语? 这三个问题答清楚,后面 6 个月你都在做同一件事 —— 把它们越挖越深。

驱动问题
你有一台 GPU、一个 70 亿参数的模型、和 100 个用户同时发来的请求。你需要让每个用户感觉自己独占这台机器。 这件事难在哪里?为什么不是 for req in requests: model(req) 就完了?
先猜:用一句话答上面的问题

有三个真实的难点:

  1. 显存有限。70B 模型自己就吃 14GB;每个用户的 KV cache 还会随对话长度线性增长。100 个用户 × 2K context 可能就把卡撑爆。
  2. 请求长度差距大。一个用户要 10 个 token,另一个要 4000 个。简单 padding 到最长 = 浪费 99% 算力。
  3. 计算节奏不同。prefill(处理 prompt)是 compute-bound,decode(一次出一个 token)是 memory-bound。混在一起 batch 就互相拖累。

vLLM 解的就是这三个问题。整套设计 = 显存复用 + 动态 batch + 调度优化

01什么是 "AI infra"

这个词被滥用得厉害。在这份教程里,它特指下面这一层

应用层 · Chat 产品 · Agent · RAG "我要给用户回话" 框架层 · LangChain · LlamaIndex · OpenAI SDK 编排、prompt 模板、agent loop ★ AI infra ★ · serving engine vLLM · TGI · SGLang · TensorRT-LLM · MLC scheduler · KV cache · batching · multi-GPU 协调 深度学习运行时 · PyTorch · CUDA · Triton tensor 算子、显存、kernel 硬件 · GPU 显存 · NVLink · PCIe · 网络
AI infra = 把上面应用层的"我要个回答"翻译成下面硬件能并行执行的指令,同时尽可能榨干显存与算力。

上面这块橙色层就是这门"infra"。 它的工作不是训练模型(那是另一个方向),也不是写 prompt(那是应用), 而是回答:给定一个已经训好的模型 + 一台 GPU + 一堆并发请求,怎么把它跑得又快又便宜?

为什么这层最有杠杆

02为什么 vLLM 是最好的锚点

有十几个 serving 引擎。为什么挑 vLLM 做主线?

维度vLLMTGISGLangTensorRT-LLM
OSS 程度✅ 完全✅ 完全✅ 完全⚠ 闭源 kernel
代码梯度Python → C++ → CUDARust + PythonPython → CUDAC++ 重度
OS 学习价值⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
新手友好✅ 文档全、GFI 多⚠ Rust 门槛✅ 但代码量少❌ NVIDIA 深绑
论文支撑SOSP'23 PagedAttentionNeurIPS'24 RadixAttention

最关键的一条:vLLM 的论文(PagedAttention)明确以 OS 虚拟内存为灵感。 这意味着你学 OS 不是绕远路 —— OS 概念就是 vLLM 的源代码注释。 这是其他项目没有的杠杆。

💡 不排斥其他项目
学完 vLLM 你会发现:SGLang 的 RadixAttention、TGI 的 router、TensorRT 的 graph capture, 本质上都在解同一类问题。vLLM 是入口,不是终点

03核心心智模型:vLLM 是 Token 的操作系统

这是整个教程最重要的一句话。展开来看:

传统 OS 干什么

有限的硬件(CPU、内存、磁盘) 分给多个进程,让每个进程感觉自己独占这台机器。 手段:虚拟内存、调度、page cache、IPC。

vLLM 干什么

有限的 GPU(显存 + SM) 分给多个请求,让每个请求感觉自己独占这块卡。 手段:PagedAttention、continuous batching、prefix cache、TP/PP。

两边的问题形状是同构的。把这条记牢:

操作系统 (CPU) 虚拟内存 + 分页 页表把虚拟页 → 物理页 进程调度器 time-slice、抢占、优先级 Page Cache 复用读过的磁盘块 Swap 把页换到磁盘缓压力 同步原语 lock / CV / monitor vLLM (GPU) PagedAttention block table 把 logical → physical block Continuous Batching 每步重组 batch、可抢占 Prefix Cache 复用共享 prompt 的 KV CPU Offload 把 KV block 换到 host RAM Worker 协调 scheduler 主循环里的锁
同一类问题在 GPU 上的"重写"。完整对照见 OS ↔ vLLM 速查

这条心智模型的实际用法

之后每读到 vLLM 一段陌生代码,你都可以问:

  1. "这相当于 OS 里的哪个机制?"
  2. "OS 里那个机制为什么这样设计?trade-off 是什么?"
  3. "vLLM 这里有没有偏离?为什么偏离?"

这套追问法,能把陌生代码变成熟悉问题的新变种,记忆负担骤降。

04一个具体例子:KV cache 为什么要分页

用上面的心智模型走一遍,体验下"思考的路径"长什么样。

Transformer 推理时,每个 token 都要存一份 K 和 V 向量供后续 attention 用。 最简单的做法是给每个请求预分配一段连续显存,假设 max_len=2048 一次性占满。这有什么问题?
先猜,再看答案

问题 1:内部碎片。如果用户实际只用 100 个 token,剩下 1948 个槽位的显存全浪费了。100 个请求 = 浪费 95%+。

问题 2:外部碎片。请求结束释放出来的连续段,未必能装下下一个新请求(如果它声明 max_len 更大)。

问题 3:分支不能共享。如果两个请求 prompt 完全一样(system prompt 相同的多用户场景),KV 没法复用。

正是 OS 1960s 解决过的问题 —— 早期 OS 也是给进程预分配连续段,后来才发明分页。

OS 的解法:把内存切成固定大小的页(typically 4KB),让进程的虚拟地址逻辑上连续、物理上分散。 页表记录映射。代价是查表开销,收益是内存利用率从 ~40% 拉到 ~95%。

vLLM 的解法:把 KV cache 切成固定大小的 block(typically 16 tokens),让每个序列的 KV 逻辑上连续、物理上分散。block table 记录映射。代价是 attention kernel 要支持非连续地址(这是 PagedAttention 论文的工程主体),收益是显存利用率 ~96%,throughput 提升 2–4x。

✓ 你的状态
如果你看到这里能大致复述上面这个对照(OS 分页 ↔ KV 分块),那么 Month 2 的内容你已经吸收了 30%。 剩下 70% 是具体怎么写代码 —— 那部分要靠读 vLLM 源码。

056 个月后你能做什么

看完路线 + 写完所有产出后,下面这些事你应该能独立完成:

这不是终点。这是"能从这往任何方向继续走"的起点。

06本页自检

读完这页,下面你应该能不查资料答出来

勾选状态会保存在你的浏览器 localStorage 里,下次打开继续。