判断 KV 卸载是否值得,需要同时核对容量预算、有效传输带宽和数据使用截止时间,再比较恢复缓存与重算的总耗时。本文用教学算例解释这些约束,并区分前缀恢复、活跃 KV 加载和 PCS 的统计口径。除明确标注 KiB、GiB 的地方外,GB 与 GB/s 均使用十进制。
两种推理负载都需要 1000 GB/s 的 KV 读取带宽。A 需要同时保留 30 GB KV,B 需要 200 GB。假设设备扣除权重等开销后,能给 KV 留出 80 GB,并在相同访问模式下持续提供 2000 GB/s。
A 的两项需求都在预算内;B 在讨论读取速度之前就已经装不下。把部分 KV 放到外层存储,能够缓解容量问题,却同时引入数据恢复与等待。
先对齐容量与带宽的口径
容量需求 表示目标并发下需要同时保留多少字节;带宽需求 表示为达到目标吞吐,在指定路径上每秒传输多少字节。一份 KV 可以只占一份空间,却在连续 Decode 中被反复读取。
将需求分别除以可用预算 与 :
图 1 容量与带宽的预算占比
同一刻度为 0–250%,每条轨道的竖线标在 100%。
负载 A
容量 30 / 80 GB · 37.5%
带宽 1000 / 2000 GB/s · 50%
负载 B
容量 200 / 80 GB · 250%,超出预算
带宽 1000 / 2000 GB/s · 50%
A 的容量占比为 37.5%,带宽占比为 50%。若两项需求按相同比例增长,带宽先碰线。当前占比不代表真实程序已经受带宽限制,还需观察计算、调度和其他访问。
B 的容量占比为 250%。如果整个工作集都要求驻留在这 80 GB 中,就缺少 120 GB;提升读取带宽无法补上空间缺口。
容量带宽比只保留了相对压力
容量除以带宽的单位是时间。设备侧 表示以该有效速率搬完一份容量需要多久;负载侧 则表示按目标访问速率搬运一份工作集的时间尺度。
本例中设备的时间尺度为 0.04 s,A 为 0.03 s,B 为 0.2 s。它们分别对应 A 的带宽余量更小、B 的容量余量更小。
但把 A 的两项需求都乘以 3, 仍为 0.03 s,实际需求却变成 90 GB 与 3000 GB/s,两项都超预算。比值适合比较压力方向,能否承接负载仍需核对绝对需求。
平均带宽够,不代表一次恢复赶得上
假设恢复路径每秒处理 10 次取回,每次搬 100 MB,链路提供 20 GB/s 的有效传输速率。平均带宽只需 1 GB/s,但一次纯传输约需 5 ms。
图 2 取回同一批 KV 时,要同时看两笔账
平均带宽需求
10 次/秒 × 100 MB/次 → 1 GB/s
单次传输耗时
100 MB ÷ 20 GB/s → 约 5 ms,按恒定速率估算
对单次恢复,可先用下面的分解审查关键路径:
这些项在实现中可能重叠,应以实际时间线校准。仅用设备标称带宽去除数据量,通常只得到理想传输部分。
小块随机访问还要检查 IOPS。固定 I/O 大小时,有 ;例如 100 万次/s、每次 4 KiB 对应 4.096 GB/s。能否达到这个吞吐,还取决于访问时延、队列深度、并发度和设备内部行为。
恢复前缀与每步加载 KV,需要分别建模
“KV Offloading”容易覆盖两种不同情形。
一种是扩大可复用前缀缓存:把已完成的前缀块留在主机内存或更外层,未来请求命中后取回,减少 Prefill。另一种是扩展当前活跃请求的工作集:Decode 过程中,每步按需从外层加载参与 Attention 的 KV。后者可能在每个输出 Token 的关键路径上产生流量。
vLLM v0.30.0 的 OffloadingConnector 文档描述了前一种用途:完成的块进入更大层级,命中后提升到 GPU。它不能直接作为“任意活跃 KV 都能透明流式执行”的证据。下一篇讨论的稀疏选块与预取,则属于需要额外设计的运行时场景。
缓存命中后,仍要与重算比较
取一个不考虑重叠的教学算例:完整 Prefill 为 100 ms;恢复命中前缀需要读取 1 GB;剩余计算为 30 ms;另有 5 ms 的恢复开销。
| 有效恢复带宽 | 纯读取耗时 | 缓存路径总耗时 | 对比完整重算 |
|---|---|---|---|
| 10 GB/s | 100 ms | 135 ms | 更慢 |
| 20 GB/s | 50 ms | 85 ms | 更快 |
两者持平所需的带宽约为:
分母若不为正,单靠提升传输带宽无法让这个串行路径优于重算。命中率提高也不保证耗时下降:计算可能减少,但要恢复的 KV 字节可能增加。
如果部分读取与计算重叠,应看数据的使用截止时间。设实际 I/O 时间为 ,从发起加载到数据必须可用之间有 的独立计算窗口,则额外等待可粗估为 。只有不依赖这批待加载数据的工作才能进入 ;不能把整次前向计算时间都算成可隐藏窗口。
用 PCS 时,先读清楚统计范围
PCS 将这些问题拆成容量计算、Footprint、Bandwidth Envelope 和 Cache Replay。不同页面的数字回答不同问题:
| 口径或模式 | 需要核对的含义 |
|---|---|
| Reference / Payload | 按指定模型与精度计算的有效数据 |
| Serialized | 加入量化元数据、Padding 等后的存储表示 |
| Reserved / Active execution | 当前执行或分配策略需要保留的空间 |
| Prefix Store / Replay resident | 前缀对象的存储口径,以及回放后实际仍驻留的对象 |
| Bandwidth Envelope | 在给定前缀命中假设下,恢复字节与计算节省是否匹配 |
| Cache Replay | 多请求竞争、共享、保护与驱逐之后,还能命中多少 |
对单个序列成立的命中比例,不能直接当成有限容量缓存面对整个请求流时的实际命中率。同样,Payload 缩小一半,也不保证预留容量、恢复流量和端到端时延一起减半。
对于复杂缓存结构,应按组件分别统计存储条目数、每条目字节与保留范围,再加总。压缩 KV、窗口状态、索引、递归状态和量化 scale 不一定具有相同的增长规律。
当容量预算、传输路径和使用截止时间都明确后,才能决定哪些 KV 留在快层,哪些可以按需取回。接下来的问题是:Top-K 给出一组块号,运行时具体怎样找到并准备这些数据?
上一篇:KV Cache 内存布局 · 下一篇:从 Top-K 到数据就绪:多级 KV 驻留与预取。