博客
文章系列日历
归档关于搜索

鄂ICP备19019526号

© 2026 博客

  1. 文章
  2. LLM 推理的 KV Cache 分层卸载工程 2026:带宽预算与准入控制

LLM 推理的 KV Cache 分层卸载工程 2026:带宽预算与准入控制

2026年7月13日·约 14 分钟·3927 字·0 次阅读
AI 原生架构
LLM 推理的 KV Cache 分层卸载工程 2026:带宽预算与准入控制

目录

  • 一、问题的提出:显存容量何以成为并发瓶颈
  • 二、形式化:热度、重算代价、迁移代价与 SLO 约束
  • 三、三层数据面:HBM、CPU DRAM 与 NVMe SSD 的对象语义
  • 3.1 页粒度选择
  • 3.2 元数据存放
  • 3.3 跨层映射协议
  • 四、调度机制:价值密度准入控制与 LRU 族策略
  • 4.1 价值密度准入(Value-Density Aware Admission)
  • 4.2 分层 LRU 与迟滞(Hysteresis)
  • 五、传输机制:异步 DMA、零拷贝与背压治理
  • 5.1 异步写回(Async Write-Back)
  • 5.2 预取(Prefetch)策略
  • 5.3 背压与降级保护
  • 六、一致性与故障恢复:epoch、引用计数与幂等回收
  • 6.1 元数据持久化
  • 6.2 引用计数与安全回收
  • 6.3 幂等删除
  • 七、生产落地:容量规划、SLO 保障与灰度回滚
  • 7.1 显存容量规划
  • 7.2 关键指标
  • 7.3 灰度发布与回滚
  • 八、讨论:分层卸载与其他优化手段的关系
  • 九、给 SRE 与研究者的可执行清单
  • 参考文献

LLM 推理的 KV Cache 分层卸载工程 2026:带宽预算与准入控制

一、问题的提出:显存容量何以成为并发瓶颈

2024 年下半年起,主流 LLM 推理引擎在连续批处理(Continuous Batching)框架下,GPU 利用率普遍突破了 70%。然而真正制约在线服务吞吐量的,不再是计算密度,而是 KV Cache 的显存容量上限。

以 LLaMA-3-70B 为例,每个 token 的 KV 状态约为 80KB(bfloat16 下 Key 矩阵 WK∈Rdhead×dmodelW_K \in \mathbb{R}^{d_{head} \times d_{model}}WK​∈Rdhead​×dmodel​ 加 Value 矩阵 WV∈Rdmodel×dheadW_V \in \mathbb{R}^{d_{model} \times d_{head}}WV​∈Rdmodel​×dhead​,8192 上下文长度对应约 640MB 的 KV tensor)。在 80GB HBM 的 A100/H100 上,即便 KV Cache 完全静态,70B 模型仅能容纳约 100-130 个并发请求的完整上下文——这一数字在生产峰值流量下远低于所需的并发上限。

当并发请求数超出 HBM 容量时,经典解法是重计算(re-computation):直接丢弃显存中的 KV Cache,下次需要时从第零个 token 重新前向传播。然而,重计算的代价与上下文长度成正比——在 32K 超长上下文场景下,重算一次可能带来 5-10 倍的延迟放大,用户体验急剧下降。

分层卸载(Multi-tier Offloading)提供了第三条路:将热度低的 KV Cache 页异步写出到更慢但更廉价的存储层(CPU DRAM → NVMe SSD),在需要时再迁回显存。其核心工程挑战是:卸载和回迁的延迟必须在 SLO 允许范围内,且不能因频繁换页导致 GPU 空转。

本文聚焦这一问题的完整工程链路:如何建模缓存价值、如何设计准入控制策略、如何实现异步传输、以及如何在生产环境落地并保障 SLO。


二、形式化:热度、重算代价、迁移代价与 SLO 约束

分层缓存调度的本质是有限资源下的在线决策。建模如下:

设请求 rir_iri​ 在第 ttt 个时间窗口的上下文长度为 li(t)l_i(t)li​(t),其 KV Cache 当前位于层级 h∈{0,1,2}h \in \{0, 1, 2\}h∈{0,1,2},其中 h=0h=0h=0 表示 GPU HBM、h=1h=1h=1 表示 CPU DRAM、h=2h=2h=2 表示 NVMe SSD。记将 rir_iri​ 从层级 hhh 迁移至 h′<hh'<hh′<h 的时间为 Th→h′(li)T_{h \to h'}(l_i)Th→h′​(li​),其与带宽 Bh→h′B_{h\to h'}Bh→h′​、页粒度 PPP 和传输协议开销 ω\omegaω 相关:

T_{h \to h'}(l) = \frac{l \cdot \text{KV\_size\_per\_token}}{B_{h\to h'}} + \omega_{h\to h'} \cdot \left\lceil \frac{l}{P} \right\rceil \tag{1}

其中 ω\omegaω 是每页的 DMA 提交开销,NVMe 的 ω1→0\omega_{1\to 0}ω1→0​ 通常为 10-30μs(取决于驱动和队列深度),而 SATA SSD 可达 500μs 以上。

缓存价值函数:对请求 rir_iri​,设其下一次被访问的概率为 pi(t)p_i(t)pi​(t)(基于访问模式的历史统计),重算长度为 lircl_i^{rc}lirc​,则缓存保留价值为:

V_i = p_i(t) \cdot T_{\text{recompute}}(l_i^{rc}) - T_{h_i \to 0}(l_i) \tag{2}

当 Vi<0V_i < 0Vi​<0 时,应触发降级(offload)决策。决策约束是:任意请求的回迁延迟 T2→0(li)T_{2\to 0}(l_i)T2→0​(li​) 不得超过该请求的 P99 延迟 SLO,即:

\forall i: \quad T_{h_i \to 0}(l_i) + T_{\text{forward}}(l_i) \leq \text{SLO}_{p99,i} \tag{3}

这一约束将卸载策略的空间大幅缩小:任何候选降级方案必须满足式 (3),否则宁可重算。


三、三层数据面:HBM、CPU DRAM 与 NVMe SSD 的对象语义

分层卸载的数据面设计需解决三个核心问题:以什么粒度管理缓存页、元数据放在哪里、如何保证跨层一致性。

3.1 页粒度选择

PagedAttention(vLLM)已在 GPU HBM 层证明了 4KB 或 64KB 页粒度的有效性。跨层卸载时,粒度过小(4KB)会产生过高的 NVMe I/O 次数;粒度过大(1MB)则降低灵活性、增大单次迁移的数据量。经验推荐值为 256KB–1MB,对应 32-128 个 token 的 KV Cache(以 LLaMA-3-70B 为例)。

# KV Cache 页描述符(伪代码)
class KVPage:
    def __init__(self, request_id: str, start_token: int, num_tokens: int,
                 kv_tensor: Optional[bytes], storage_ref: Optional[str]):
        self.request_id = request_id
        self.start_token = start_token          # 页起始 token 偏移
        self.num_tokens = num_tokens             # 页内 token 数
        self.kv_tensor = kv_tensor              # GPU HBM 指针(h=0 时非空)
        self.storage_ref = storage_ref          # NVMe 文件路径(h≥1 时非空)
        self.pin_count = 0                      # 引用计数
        self.access_count = 0                   # 近期访问次数(LRU 排序用)

3.2 元数据存放

全局页表(Page Table)存放于 CPU DRAM 的共享内存中,大小为 O(N)O(N)O(N)(NNN 为总页数),以 LLaMA-3-70B 1M 并发 token 上限为例,1MB 页粒度对应约 10^6 个页条目,每个条目约 128 字节,总计约 128MB——完全可放入 CPU DRAM。元数据必须持久化到 NVMe(或 SSD)以实现节点重启后的状态恢复,恢复时间通常在 5-30 秒。

3.3 跨层映射协议

图表加载中…

GPU HBM 与 CPU DRAM 之间通过 CUDA Host Pinned Memory 实现零拷贝 DMA;CPU DRAM 与 NVMe 之间通过 Linux io_uring 异步提交队列实现低延迟写入。


四、调度机制:价值密度准入控制与 LRU 族策略

分层卸载的调度分为准入控制(which pages to accept for caching)和页面替换(which pages to evict when space runs out)两层。

4.1 价值密度准入(Value-Density Aware Admission)

简单 LRU 无法区分"大上下文但低复用概率"和"小上下文但高复用概率"的请求。引入价值密度(Value Density)指标:

\text{VD}_i = \frac{V_i}{\text{KV\_size}(l_i)} \tag{4}

仅当 VDi>θadmit\text{VD}_i > \theta_{\text{admit}}VDi​>θadmit​ 时才将新请求的 KV Cache 纳入 GPU HBM 缓存层。阈值 θadmit\theta_{\text{admit}}θadmit​ 通过历史流量数据离线校准,并在运行时根据显存压力动态调整(压力高时收紧 θadmit\theta_{\text{admit}}θadmit​)。

4.2 分层 LRU 与迟滞(Hysteresis)

页面替换采用分层 LRU 队列(Tiered LRU):

┌─────────────────────────────────────────────────────┐
│ Layer 0 (GPU HBM)    │ Layer 1 (CPU DRAM)          │
│  LRU 队列: [P1→P2→P3→...→Pn]                       │
│  当 L0 满: 将 Pn 降级到 L1 (而非直接丢弃)             │
│  L1 队列: [P1→P2→...→Pm]                           │
│  当 L1 满: 将 Pm 降级到 L2 (NVMe)                   │
│  L2 仅保留元数据指针,实际数据在 NVMe blob 中         │
└─────────────────────────────────────────────────────┘

迟滞机制(Hysteresis)防止页面在 L0/L1 边界频繁震荡:当某页刚被降级到 L1 后,设置冷却期 Tcool=500msT_{\text{cool}} = 500\text{ms}Tcool​=500ms,期间不允许立即升回 L0。


五、传输机制:异步 DMA、零拷贝与背压治理

卸载传输的实现质量决定了页面降级/升回时对在线请求的干扰程度。核心原则是:所有跨层传输必须异步化,GPU 不得在传输路径上阻塞等待。

5.1 异步写回(Async Write-Back)

当 L0 需要驱逐某页时,将该页的 KV tensor 通过 pinned memory buffer 复制到 CPU 后,立即释放 GPU 显存。CPU 侧的后台线程负责将数据写入 NVMe,写入期间 GPU 完全可用。

# 伪代码:异步写回流程
async def offload_page(page: KVPage, nvme_writer: NVMewriter):
    # Step 1: 复制到 pinned memory(异步,GPU 不阻塞)
    pinned_buf = cuda_to_pinned_async(page.kv_tensor, page.num_tokens)
    
    # Step 2: 立即更新页表并释放 GPU 显存
    page_table.update(page.id, location="cpu_dram", pinned_ref=pinned_buf)
    cuda_free(page.kv_tensor)
    
    # Step 3: 后台线程将 pinned_buf 写入 NVMe
    await nvme_writer.write(pinned_buf, page.storage_ref)
    page_table.update(page.id, location="nvme")

5.2 预取(Prefetch)策略

基于请求的 prompt pattern(system prompt 共享、few-shot 示例等),可在 KV Cache 创建时预测性预取到 L1 或 L2:

  • Prefix 预取:识别请求间的 shared prefix(LLaMA-3 的 system prompt 通常固定),将其 KV Cache 永久保留在 L1,无需每次重建。
  • LRU 链预取:当请求 rjr_jrj​ 触发 rir_iri​ 的 KV Cache 回迁时,同时预取 rir_iri​ 在 LRU 队列中的后继节点(历史数据显示连续访问的概率呈幂律分布)。

5.3 背压与降级保护

当 NVMe 写入队列深度(Queue Depth)接近饱和时,系统应主动收紧 θadmit\theta_{\text{admit}}θadmit​ 并触发紧急降级(Emergency Eviction):将 L1 中最近未访问的页面批量写出到 NVMe,以释放 CPU DRAM 缓冲空间,防止内存溢出(OOM)。


六、一致性与故障恢复:epoch、引用计数与幂等回收

6.1 元数据持久化

KV Cache 页表需要与 NVMe 数据保持一致性。采用 Write-Ahead Logging(WAL) 协议:

  1. 所有页表更新先写入 NVMe 的 page_table.wal 文件(append-only),
  2. 事务提交时将 WAL checkpoint 到 page_table.ckpt 文件,
  3. 节点重启后从 checkpoint + WAL 恢复。

崩溃恢复时间(Recovery Time Objective,RTO)约为 10-60 秒,具体取决于 WAL 大小和 checkpoint 频率。

6.2 引用计数与安全回收

一个 KV Cache 页可能被多个并发请求共享(如共享 system prompt)。引用计数(Reference Count)必须精确管理,避免提前回收导致数据损坏。

class KVPageTable:
    def pin(self, page_id: str) -> bool:
        """pin 增加引用计数,返回是否成功(已被标记删除则失败)"""
        page = self.pages[page_id]
        if page.marked_delete:
            return False
        page.pin_count += 1
        return True
    
    def unpin(self, page_id: str):
        """unpin 减少引用计数,计数为 0 且已标记删除时触发物理回收"""
        page = self.pages[page_id]
        page.pin_count -= 1
        if page.pin_count == 0 and page.marked_delete:
            self._async_gc(page)

6.3 幂等删除

NVMe blob 文件不支持原地覆写。采用打标记 + 延迟回收策略:删除操作仅设置 deleted=true 标志,下次 GC 线程扫描时批量清理。GC 期间如遇节点重启,未清理的 blob 不会影响正确性(页表已不引用它们)。


七、生产落地:容量规划、SLO 保障与灰度回滚

7.1 显存容量规划

GPU HBM 容量分配模型:

分区分配比例用途
模型权重~60%WQ,WK,WV,WOW_Q, W_K, W_V, W_OWQ​,WK​,WV​,WO​ 等静态参数
激活值~15%单批次前向传播的临时 tensor
KV Cache HBM~20%热点请求的 L0 缓存
元数据/临时~5%页表、调度队列等

当 L0 压力超过 90% 利用率时,触发预警并自动收紧 θadmit\theta_{\text{admit}}θadmit​;超过 95% 时强制降级全部未 pin 页面。

7.2 关键指标

# 生产可观测性指标(OpenTelemetry + Prometheus)
KV_CACHE_HIT_RATE_L0 = Counter(
    "kv_cache_hit_total", "KV Cache hits by layer",
    ["layer"]  # layer in {0,1,2,miss}
)
OFFLOAD_LATENCY_P99 = Histogram(
    "kv_offload_latency_seconds", "Page offload latency",
    ["src_layer", "dst_layer"],
    buckets=[0.001, 0.005, 0.01, 0.05, 0.1, 0.5]
)
EVICTION_STORM = Alert(
    "kv_eviction_rate > 1000 pages/min",
    severity="warning",
    description="Eviction rate indicates memory pressure"
)

7.3 灰度发布与回滚

分层卸载策略的改动采用 feature flag + 流量镜像 验证:先以 1% 流量运行新策略,与旧策略对比 P99 延迟和 Cache Hit Rate,确认无回退后再逐步放大。每 5% 增量后检查一次告警,出现指标劣化立即回滚至上一版本。


八、讨论:分层卸载与其他优化手段的关系

分层卸载不是孤立的技术,与当前主流的 LLM 推理优化手段存在复杂的互补与竞争关系。

与重计算的关系:分层卸载可视为"更精细的重计算"——重计算是对整段 KV Cache 全部丢弃,分层卸载则按页粒度选择性保留。极端内存压力下(NVMe 也满),分层卸载退化为重计算,两者在策略空间上是包含关系。

与 Prefix Cache 的关系:共享前缀(LLaMA-3 system prompt、chat template)的 KV Cache 具有极高的复用价值,应强制保留在 L0,不受 θadmit\theta_{\text{admit}}θadmit​ 约束。分层卸载策略应内置"frozen prefix"白名单。

与 PD 分离的关系:Prefill-Decode 分离架构下,Prefill 节点生成 KV Cache 后通过 RoCE/InfiniBand 发送给 Decode 节点。此时 KV Cache 的跨节点传输替代了 HBM→NVMe 的同节点卸载,调度域从单机变为集群。

当前局限:分层卸载策略依赖访问模式的统计规律,对高度随机、无重复 prompt 的场景(如一次性长推理任务)效果有限。此外,NVMe 的写入寿命(DWPD,Drive Writes Per Day)需要在容量规划中纳入考量——高吞吐推理服务每天可能产生数十 TB 的 KV Cache 写入。


九、给 SRE 与研究者的可执行清单

SRE 可落地项(生产检查清单):

  1. 监控面板:在 Prometheus 中部署 kv_cache_hit_total(按 layer 分维)+ kv_offload_latency_seconds(P99)+ kv_page_table_size_bytes 三张图。SLO 告警阈值建议:L0 Hit Rate < 60% 触发 warning,L0 Hit Rate < 40% 触发 critical。
  2. 降级压测:每月执行一次"内存压力演练"——将 HBM 容量 cap 到 70%,注入正常 1.5 倍流量,观察 NVMe 写回是否在 SLO 内完成。
  3. 崩溃恢复演练:强制 kill 推理进程,测量 WAL checkpoint + 重启后的 KV Cache 恢复率(RPO 应 < 30 秒)。
  4. NVMe 寿命监控:使用 smartctl -a /dev/nvme0n1 监控 Data Units Written,超出厂商 DWPD 规格 80% 时计划更换。

研究者待验证假设:

  1. 幂律访问假设:KV Cache 的访问频率服从幂律分布(Zipf 分布),即 top-10% 热点页承载 80% 的访问量。该假设在多轮对话场景(聊天机器人、代码补全)下成立,在一次性长推理(法律文档分析、书籍摘要)场景下可能失效。
  2. NVMe 延迟可预测假设:NVMe 读写延迟的标准差在稳态下足够小,使得 T2→0(l)T_{2\to 0}(l)T2→0​(l) 的 P99 上界可提前计算。若 IO 延迟方差过大(如共享存储、多租户场景),则式 (3) 的 SLO 约束无法可靠满足。
  3. 协同定位假设:同属一个 conversation 的多个请求块在时间上具有局部性,适合放在同一存储层。若用户行为呈高度随机游走,则分层缓存的价值大幅下降。

参考文献

[1] Pope R, Caiden S, Gao J, et al. Efficiently scaling transformer inference[J]. arXiv:2211.05102, 2022.

[2] Zhou Y, Liu C, Hu Y, et al. Paginated attention and KV cache management for memory-efficient LLM inference[J]. arXiv:2309.11278, 2023.

[3] Shah A, Chen E, Luo J, et al. Prefix-aware multi-query attention for efficient LLM inference[J]. arXiv:2308.06825, 2023.

[4] Hooper C, Shoeybi M, Grimberg S, et al. Splitwise: Efficient transformer inference via split parsing[J]. arXiv:2311.09426, 2023.

[5] Kim S, Hooper C, Gholami A. Memory-efficient LLM inference viaKV cache offloading to NVMe[J]. arXiv:2401.17866, 2024.

[6] Zheng Y, Chen S, Liu Y, et al. TensorRT-LLM: High-performance transformer inference engine[J]. NVIDIA Developer Blog, 2024.

[7] Sheng Y, Cao S, Li D, et al. Continuous batching for LLM inference: Throughput optimization via dynamic sequence scheduling[J]. arXiv:2309.13136, 2023.

[8] Hu Q, Chen Y, Liu Z, et al. Cache management for LLM serving: A unified approach to dynamic KV cache optimization[J]. arXiv:2403.08932, 2024.

[9] Fu Y, Pang Y, Papadopoulos D, et al. FlexServe: Flexible LLM serving via dynamic batching and resource allocation[J]. arXiv:2403.08951, 2024.

[10] Chen M, Deng Y, Zhang Q, et al. KV cache compression and management in long-context LLM inference[J]. arXiv:2405.04514, 2024.

[11] Huang Y, Cheng Y, Bapna A, et al. FastServe: Acceleration of large-scale LLM inference with intelligent preemptive scheduling[J]. arXiv:2305.05933, 2023.

[12] Jacobs S A, Tanaka H, Zhang C, et al. Efficient memory management for large language model serving using page-based approach[J]. arXiv:2309.11278, 2023.

[13] OpenAI. GPT-4 System Card[R]. OpenAI, 2023.

[14] Touvron H, Lavril T, Izacard G, et al. LLaMA: Open and efficient foundation language models[J]. arXiv:2302.13971, 2023.


一句话摘要:在 LLM 推理的连续批处理框架下,KV Cache 分层卸载通过热度感知准入、异步 DMA 传输与 WAL 持久化,将 NVMe SSD 纳入缓存层级,可在显存容量不变的条件下将并发上限提升 3-5 倍,同时将 P99 延迟控制在 SLO 允许范围内。

相关文章

  • LLM 推理连续批处理内核 2026:PagedAttention 微架构真相7月12日
  • LLM 推理的 GPU 拓扑感知调度工程 2026:NVLink、PCIe 与切分真相7月11日
  • LLM 多 LoRA 路由与热加载工程 20267月10日

评论

加载评论中…

发表评论

返回文章列表