全景导读:先把一次请求的整条链路想明白
1. LLM Infer Infra 到底做什么
模型训练好以后,直接写一个 generate() 就能得到回答。但真实服务还要面对几百个用户同时提问、有人输入几万字、有人只问一句话、有人生成到一半取消请求。GPU 很贵,显存有限,机器也会故障。
LLM Infer Infra 做的就是把“能生成答案”变成“很多人一起用时,依然足够快、足够稳,成本还可控”。常见工作包括:
| 现实问题 | 工程上做什么 | 对应方向 |
|---|---|---|
| GPU 只服务一个请求时利用率低 | 把多个请求组织成批次,按轮次持续补入新请求 | 推理引擎与调度 |
| 长请求占满显存,短请求排队 | 管理 KV、限制准入、分块 Prefill、处理抢占 | 引擎与内存管理 |
| 每个用户都重复提交同一份长文档 | 复用已算出的前缀 KV,减少重复 Prefill | 缓存管理 |
| 一个实例有缓存,另一个实例又重算 | 把缓存放进共享池,设计查找、放置与加载 | 分布式 KV 存储 |
| 缓存找到了,搬回来却很慢 | 优化内存注册、网络、布局、批量传输与流水线 | 高性能通信 |
| 单机测试很快,线上 P99 很差 | 分解排队、执行、通信,做容量与过载管理 | Serving 平台 |
学习时不要先按项目名字背功能。先知道自己在解决哪个问题,再找承担这件事的组件。
2. 一次聊天请求经历了什么
假设用户提交“请总结下面的合同”,后面附了 8,192 个 token 的输入,要求生成 256 个 token。
- 入口接收请求。 校验参数、套聊天模板、分词,把文本变成 token IDs。相同可见文本不一定产生相同输入:模板、tokenizer 和特殊 token 也会改变结果。
- 路由与排队。 选择实例,进入调度队列。此时模型可能还没开始算;“首字慢”经常先慢在这里。
- 检查已有 KV。 如果这份合同前面 6,144 个 token 的完整前缀已经算过,尝试复用。数据可能在 GPU、CPU 或另一台机器上。
- 准备数据与 GPU 空间。 命中远端只代表存在候选对象;还得把数据搬到正确的 GPU block,确认所有必需分片就绪。
- Prefill。 计算没有复用的输入部分,建立对应 KV。最后位置的 logits 通常用来采样第一个输出 token。
- Decode。 将新 token 输入下一轮计算,每轮利用已有 KV 生成后续 token,同时追加新状态。
- 返回与清理。 输出增量文本;结束或取消后释放请求资源,可复用 KV 按缓存策略保留。异步传输尚未结束的内存需要延后回收。
客户端
↓
入口 / 模板 / 分词 / 路由
↓
推理引擎:排队 → 查缓存 → 分配空间 → Prefill → Decode
│ ↑
│ 本地或远端 KV 加载
↓ │
输出返回 缓存管理 → 共享存储 → 数据传输
“缓存优化”只改变其中一部分成本。它可能减少 Prefill,却增加查询、搬运、内存占用和排队。必须看整条请求是否受益。
3. 按职责理解系统分层
| 层次 | 持有什么状态,决定什么事情 | 深入入口 |
|---|---|---|
| 推理运行时 | 请求队列、执行进度和设备任务,决定每轮计算 | 运行时 |
| KV 管理 | 页、前缀、引用、分层与加载状态,决定能复用什么 | KV 管理 |
| 分布式存储 | 对象目录、位置、副本和保护状态,决定怎样保存与读取 | 存储 |
| 数据传输 | buffer、连接、注册、在途任务与完成状态,执行字节移动 | 传输 |
| Serving 平台 | 路由、资源池、准入、服务目标与观测,协调端到端行为 | Serving 与性能 |
这是一种职责划分,不要求每一层都单独运行一个服务。具体实现可能把缓存控制放在运行时,也可能独立部署;共享存储可以使用独立传输引擎。各主题内部再用开源实现说明边界。
4. 先认清三条常见组合
组合 A:只有推理引擎
推理运行时 → GPU KV + 本地前缀缓存
单实例、短输入、低复用时,先把这一层做好。引入外部服务也有成本。
组合 B:推理引擎加共享缓存
推理运行时
→ 缓存接入与分层控制(内置或独立服务)
→ 共享对象存储
→ 适用的数据传输路径
先决定缓存控制放在哪里、数据怎么保存和恢复,再选具体组件。需要核对模型支持、缓存格式、资源所有权和故障行为;插件之间不一定能任意组合。
组合 C:Prefill 与 Decode 分开
Prefill 实例 → 状态交接与数据传输 → Decode 实例
这条链路解决同一次请求的状态交接;共享缓存解决不同请求重复计算的问题。两者可以一起用,也可以单独用。
5. 为什么 KV Cache 存储岗需要懂推理
普通对象存储只需知道“这个 key 对应这些 bytes”。KV 存储系统还必须回答:
- 这些 bytes 是哪个模型、哪个版本、哪个前缀算出来的?
- 是哪一个 TP rank、哪一组 layer 的状态,布局是否匹配目标引擎?
- 命中的是连续前缀,还是零散几个无法直接跳过计算的片段?
- 拉回来需要多少时间,是否比重新计算更快?
- 数据读完了吗,GPU 可以使用了吗,原始 buffer 可以释放了吗?
如果这些问题由上层 Connector 负责,存储工程师也要理解这个契约。否则容易出现“存储测试全部通过,推理输出偶尔错误”的问题。
6. 用三个问题检查整体认识
客户说“首字慢”,先改哪个组件? 先拆分入口、排队、查缓存、加载、Prefill、首 token 返回时间。没有分段数据时,直接调 RDMA 或 batch size 都是在猜。
客户说“显存不够”,加共享存储一定解决吗? 不一定。外部存储能扩大可保留的 KV 总量,但正在执行的 attention 仍需要适用的 GPU 状态和工作空间;权重、并发、临时张量也占显存。
客户说“命中率 90%,为什么没快”? 要确认命中了多少 token、命中哪一层、是否成功加载、是否减少实际计算,以及搬运和排队是否吃掉收益。
把这三件事想清楚,再读公共基础,就能把术语放回真实问题里。