从云原生走向 AI 原生:一套面向未来的架构方法论 → 阅读《AI 原生基础设施》

LLM 推理的物理层:预填充、解码与 KV 容量账

草稿

推理平台的所有配置争论(并发、批大小、显存水位、共享粒度)最终都归结为两笔物理账:一笔算力账,一笔显存账。

vLLM一章从资源治理视角讨论吞吐与尾延迟;本章补上它的物理地基:为什么解码受带宽屋顶线约束、为什么 KV cache 是容量货币、为什么连续批处理和分页 KV 是必然设计。这些账同样决定Kthena一类的推理调度器在优化什么。Roofline 模型的推导见微架构,显存机制见显存管理

两阶段:同一模型,两种性格

  • 预填充(prefill):一次性并行处理整条 prompt,生成第一个 token。大矩阵乘法,受算力屋顶线约束,是 GPU 的舒适区。
  • 解码(decode):此后每生成一个 token,都要带着全部历史(KV cache)再算一遍前向。每步计算量小,但每步都要把全部模型权重从显存读一遍,受带宽屋顶线约束。

由此得到推理平台最实用的一行公式:

单路解码速度上限 ≈ 显存带宽 ÷ 权重量
H100 (3.35 TB/s) 跑 70B BF16 (140 GB) ≈ 24 token/s(物理规律,不是软件差)

它解释了三件事:量化(FP8 权重减半)直接让解码翻倍;换带宽更高的卡(H200)比换算力更高的卡对推理更有效;以及批量推理的本质是把“读一遍权重”摊到多个请求上,把算术强度从 1 提高到 B。吞吐随批量大致线性上升,直到撞上算力屋顶线或显存容量。

KV cache:容量货币

自回归生成需要缓存每个 token 的 Key/Value 向量:

每 token KV 字节数 = 2(K与V) × 层数 × KV头数 × 头维度 × 精度字节
Llama-3-70B (80层, 8 KV头, 头维128, BF16) = 320 KB/token
→ 一个 4k 上下文的请求 ≈ 1.25 GB 显存

GQA(分组查询注意力)是现代模型 KV 变小的原因:Llama-3-70B 用 8 个 KV 头对应 64 个查询头,KV 比 MHA 等效结构小 8 倍。架构选择直接等于容量选择。

推理容量公式(平台做容量规划时的第一行代码):

可并发请求数 ≈ (显存总量 × 利用率 − 权重 − 激活/开销) ÷ (每token KV × 平均上下文)

示例(H100 80G,利用率 0.9,4k 平均上下文):8B 模型单卡约 100+ 并发;70B 需要 TP=8 才有合理并发;32B 级模型在单卡只剩个位数并发,这就是“中等模型为什么也要 TP”的算术。

连续批处理与分页 KV:两次必然的进化

静态批(攒一批一起进出)的浪费是显然的:长短请求互相等,新请求必须等整批结束。**连续批处理(continuous batching)**在每个解码步重新组批:完成的请求下车、排队的新请求上车。这是 vLLM/TRT-LLM/SGLang 的共同底座。

连续批处理把压力转移到内存管理:早期引擎按“最大长度”为每个请求预留连续显存,浪费 60–80%。分页 KV(PagedAttention)把操作系统的分页机制搬进显存:

操作系统概念分页 KV 对应
物理页(4KB)KV 块(默认 16 token)
页表每请求的 block table
写时复制(COW)采样 n>1 / beam 分叉时共享块
共享库页缓存前缀缓存:相同 system prompt 的请求共享已算好的块
swap显存不足时把块换到主机内存
表 1: 分页 KV 与操作系统分页的对应

其中前缀缓存对平台价值最大:RAG/Agent 类“长固定前缀 + 短输出”的流量,块级节省可达 90% 以上,同样显存服务多一个数量级的并发,且 TTFT 大幅下降。前缀命中率应当与 KV 水位一起纳入容量模型与验收指标

分块预填充:吞吐与尾延迟的调节阀

一条 16k prompt 的预填充是一个百毫秒级的大 kernel;若引擎“先做完预填充再解码”,期间所有正在解码的请求都停摆,TTFT 与 ITL(token 间延迟)天然冲突。**分块预填充(chunked prefill)**把长 prompt 切块掺进解码批逐步消化,用少量 TTFT 换取 ITL 的稳定。更激进的方案是预填充/解码分离部署(如 Kthena 一类调度器的 PD 分离模式),把冲突移到集群层,代价是 KV 迁移与路由复杂度。

与共享/配额层的配合:一道必考题

推理引擎按 gpu_memory_utilization × 物理显存 计算自己的 KV 池。在软切分配额(HAMi 的 nvidia.com/gpumem)下,若 Pod 配额 40GB 而机器 80GB、utilization 拍 0.9,引擎会按 72GB 规划显存池,配额拦截层在池初始化时注入 OOM,Pod 进入启动崩溃循环。正确做法是让两个数字来自同一个变量:

gpumem 配额 ≈ 权重/TP + 期望KV池 + 激活/图/上下文底噪(约2-3GB)
gpu_memory_utilization ≈ gpumem ÷ 物理显存    ← 从配额反推, 而不是拍 0.9

同理,core 份额(nvidia.com/gpucores)对解码型负载的限流效果天然偏弱:它管的是执行时间,而解码的瓶颈在带宽(见微架构的 Roofline 模型)。推理租户的配额要以显存为主、算力为辅,且同卡邻居的负载类型比份额数字更影响尾延迟(见vLLM的抖动分析与指标语义)。

常见误区

误区真相
推理 GPU 只用了 5% 算力,太浪费解码受带宽屋顶线约束,5% 算力可能是物理最优;看 DRAM 指标
并发越大吞吐越高过拐点后只伤延迟,且显存容量先耗尽
前缀缓存是个小优化长固定前缀流量下是数量级的容量与 TTFT 收益
量化伤质量所以不用权重量化在评测上普遍近无损,且是带宽优化的第一手段
vLLM 已经做多租户了,平台不用管引擎内是请求级公平;副本层的配额、伸缩、隔离仍是平台职责
分离部署一定更好引入 KV 迁移与路由复杂度;规模或 SLO 不极端时分块预填充常常足够
表 2: 推理物理层的常见误区

总结

推理的物理层可以压缩成三句话:解码是带宽问题(单路上限 = 带宽 ÷ 权重量,量化与高带宽卡是正解);KV cache 是容量货币(并发、模型选型、TP 宽度都按 KV 账算);批处理与分页是结构解(连续批把算术强度提上去,分页把浪费降下来,前缀缓存再省一个量级)。下一章vLLM把这些物理事实映射为资源治理旋钮;可观测告诉你用哪三个数字确认系统运行在预期区间。

参考资料

创建于 2026/08/28 更新于 2026/08/28 2258 字 阅读约 5 分钟