Tutti: Making SSD-Backed KV Cache Practical for Long-Context LLM Serving

framework 2605.03375
kv-cache-offloadinggpu-centric-storagenvme-ssdprefix-cachingio-scheduling

Tutti: Making SSD-Backed KV Cache Practical for Long-Context LLM Serving #

Shi Qiu, Yifan Hu, Xintao Wang, Wenhao Zhu et al. | 2026-05 | Category: framework | Tags: kv-cache-offloading, gpu-centric-storage, nvme-ssd, prefix-caching, io-scheduling

§1 TL;DR #

Tutti 是首个将 CPU 从 GPU↔SSD KV cache 的数据路径和 I/O 控制路径中完全移除的开源方案。通过 GPU-native object store + GPU io_uring + slack-aware I/O scheduling 三项设计,SSD-backed KV cache 达到与 DRAM-backed 近乎相同的推理性能,TTFT 降 78.3%、可服务 RPS 翻倍、成本降 27%。

System scope #

§2 Q1 / Q2 / Q3 #

Q1 痛点 #

  1. KV cache 容量瓶颈:长上下文 + 高并发使 KV cache 远超 HBM / DRAM 容量;SSD 提供 100 TB 级容量但 I/O 无法跟上推理速度。
  2. CPU-centric I/O 是根因:paged KV layout 碎片化 → 数十万次小粒度随机 I/O 全部需 CPU 发起(即便 GDS 亦然),GPU stall 高达 70–80%。
  3. 随 compute 优化加剧:vLLM v0.12 → v0.17 推理加速后 I/O 比重更大,SSD-backed KV cache 收益从"不佳"变为"负收益"。
  4. Q2 方法 #

    Design 1 — GPU-centric Object Store (§3.1):将 KV cache 抽象为 GPU file($2L$ objects/file),NVMe file 以 Tensor-Stripe 布局对齐 GPU 内存 block 粒度。P2P memory mapping table 使用 SGL 取代 PRP(HBM 开销从 3.75 GB 降至 15 MB)。CPU 开销从 $O(\text{layer} \times \text{blocks})$ 降为 $O(\text{layer})$。

    Design 2 — GPU io_uring (§3.2):CPU 仅异步提交 IOCB,GPU kernel 在 HBM 驻留的 lock-free ring buffer (SQ/CQ) 上完成 NVMe 命令提交与完成轮询。SM partitioning(NVIDIA green context)将 GPU 资源硬隔离为 Compute Domain 和 I/O Control Domain,消除长尾延迟。

    Design 3 — Slack-aware I/O Scheduler (§3.3):离线 profiling 建表记录每层($L_\text{input}$, $L_\text{prefix}$)下的 SM 空闲窗口。运行时查表调度 read/write,解耦 R/W 避免 NVMe 内部 cache 抢占(混合 R/W 带宽跌 60%)。Read 优先;write 延迟到后续 slack 或 decode 阶段。

    核心技术壁垒 #

    GPU-side 全程绕过 CPU 的 NVMe I/O 控制路径是最难复现的核心。它要求:(1) GPU 驱动直接管理 NVMe SQ/CQ(BaM/GeminiFS 技术栈);(2) SGL descriptor 替代 PRP 以避免特权态 CPU 分配页表;(3) SM 硬隔离保证 I/O kernel 不与 compute 争抢——三者缺一不可,且需要对 NVMe 规范和 GPU 硬件调度器有底层控制力。

    Q3 结果 #

    MetricTuttiBest BaselineDelta
    TTFT (LEval, vLLM v0.17, SLO 1s)lowestLMCache-GDS−78.3%
    Achievable RPS (SLO-bounded)2× GDSLMCache-GDS+100%
    Retrieve BW (2-disk, 128K)25.9 GB/sLMCache-GDS 11.9 GB/s+2.08×
    Cost per 1M tokens (LooGLE)lowestLMCache-SSD−66.2%
    Crossover hit rate (compute→I/O bound)98.3%LMCache-SSD ≪
    Multi-GPU TTFT 640K1.2 sGDS: OOM

    §3 架构 / 方法图 #

    Figure 1: CPU-centric vs GPU-centric KV cache storage architecture

    Paper's Figure 1, verbatim (caption: "Comparison between CPU-centric KV cache storage (LMCache w/ and w/o GDS) and GPU-centric Tutti. Tutti eliminates CPU intervention from the critical data and I/O control paths between HBM and SSDs.").

    Figure 1 是 Tutti 的核心对比:左侧 CPU-centric 路径中每次 I/O 都经 CPU 发起 cudaMemcpy 或 GDS cuFile 调用;右侧 GPU-centric 路径中 CPU 仅做一次性元数据准备,数据流完全在 GPU→NVMe 之间闭环。

    Figure 4: Layout of GPU-centric KV cache object store

    Paper's Figure 4, verbatim (caption: "Layout of GPU-centric KV cache store.").

    GPU file pool 将每个 KV block 映射为一个 GPU file($2L$ objects:K/V 各一层一 object)。NVMe file pool 基于 GeminiFS 预分配 extent。P2P memory mapping table 在初始化时从 KV cache memory pool 的虚拟地址预算好 SGL 描述符,运行时零开销查表。

    Figure 5: GPU io_uring architecture and I/O flow

    Paper's Figure 5, verbatim (caption: "Architecture and I/O Process of GPU io_uring.").

    gio_uring 的四步流程:init_queueget_iocb(CPU 填充 IOCB)→ issue_io(GPU kernel 在隔离 SM 上发射 NVMe 命令)→ wait_cqe(GPU 端 poll CQ,无 CPU 参与)。CUDA event 用于保证跨 stream 依赖正确性。

    Figure 7: Slack-aware I/O scheduler

    Paper's Figure 7, verbatim (caption: "Slack aware I/O scheduler.").

    Scheduler 在 prefill 每层前查表获取空闲 SM 窗口,优先调度 read kernel,write kernel 利用剩余 slack 或 defer 到 decode。解耦设计避免 NVMe SSD 内部 cache 因混合 R/W 而带宽坍塌。

    sequenceDiagram participant CPU as CPU (off-critical-path) participant GPU_C as GPU Compute Domain participant GPU_IO as GPU I/O Domain participant NVMe as NVMe SSD CPU->>GPU_C: enqueue compute kernel (layer L) CPU->>GPU_IO: enqueue I/O kernel (IOCB for layer L+1) Note over CPU: CPU overhead = O(layer), then idle GPU_C->>GPU_C: prefill layer L (attention + FFN) GPU_IO->>NVMe: issue SGL read (layer L+1 KV) NVMe-->>GPU_IO: DMA completion → CQ entry GPU_IO-->>GPU_C: CUDA event signal (KV ready) GPU_C->>GPU_C: prefill layer L+1 (uses fetched KV) Note over GPU_IO: write deferred to slack/decode GPU_IO->>NVMe: issue SGL write (layer L KV store)

    §4 作者证明 #

    无形式化性能模型 — 仅实证 + 成本模型 #

    论文没有提出 I/O 性能的解析吞吐/延迟模型,而是依赖离线 profiling lookup table 来做调度决策。唯一显式模型为 §4.3 的成本公式。

    Notation table #

    SymbolMeaningUnit
    $P_{GPU}$GPU hourly rental price$/hour
    $N_{GPU}$GPU count
    $P_{mem}$DRAM unit price$/GB/hour
    $S_{mem}$DRAM capacity provisionedGB
    $P_{ssd}$SSD unit price$/GB/hour
    $S_{ssd}$SSD capacity provisionedGB
    $\text{Throughput}$Achieved token generation ratetokens/hour

    方程物理意义 #

    $$\text{Cost}_{1M} = \frac{P_{GPU} \cdot N_{GPU} + P_{mem} \cdot S_{mem} + P_{ssd} \cdot S_{ssd}}{\text{Throughput}} \times 10^6$$

    分子 = 硬件总小时成本(计算 + 存储)。分母 = 该配置下实际达成的吞吐。物理含义:在 GPU 利用率不变时,用更便宜的 SSD 替代 DRAM 直接降低分子;但如果 SSD I/O 拖累利用率使 throughput 下降,则分母减小 → cost 上升。Tutti 的贡献在于保持 throughput ≈ DRAM-backed 的同时让存储成本项降 ~100×。

    6-check verification #

    1. 维度一致:\[$/hour\] / \[tokens/hour\] × \[10^6\] = \[$/Mtok\] ✓
    2. 边界检查:throughput → 0 时 cost → ∞(GPU idle = 最贵),符合直觉 ✓
    3. 单调性:cost 关于 throughput 单调递减;关于 $S_{mem}$/$S_{ssd}$ 单调递增 ✓
    4. 数值代入:$P_{GPU}=5, N_{GPU}=1, P_{ssd}=0.000082, S_{ssd}=14000$ → 存储项 $\approx$1.15$/hr ≪ GPU 5$/hr;DRAM 同容量 1232$/hr → 差 1000× ✓
    5. 模型局限:未计算 I/O 带来的 GPU bubble 对 throughput 的折扣,实际通过实验补全 ✓
    6. 与实验对应:Fig. 14 中 Tutti cost 最低与公式预测一致 ✓
    7. 无形式化 I/O 性能模型的缺失影响 #

      一个理想的 I/O 模型需刻画:(a) per-layer transfer time $T_\text{xfer}(B, n_\text{disk}, \text{req\_size})$;(b) compute slack $T_\text{slack}(L_\text{input}, L_\text{prefix}, \text{layer})$;(c) crossover condition $T_\text{xfer} > T_\text{slack}$ 的解析解。缺失此模型意味着无法在不同硬件(更多/更少 SSD、不同 GPU)上快速预测 Tutti 的表现界限。

      §5 实验与数据 #

      Scheduling & resource management (framework-specific) #

      I/O 调度粒度: layer-level(每层一次 retrieve/store 决策)。

      Preemption: 无——I/O kernel 一旦在 I/O Domain 上发射不可抢占,但通过 slack-aware 调度保证不阻塞 compute kernel。

      Admission control: 依赖 vLLM 原有 scheduler 做 request-level admission;Tutti 不做额外准入控制。

      Memory management:

      • KV cache allocation unit = vLLM page block(16–64 tokens × heads × dim)
      • Fragmentation: Tensor-Stripe 布局 + 预分配 NVMe file pool 消除运行时碎片
      • Eviction / reuse: 继承 vLLM prefix cache 策略;Tutti 通过 Mooncake 做 cluster-level replica metadata 管理
      • Swap: SSD 即最终持久层,无 CPU swap;retrieve 是从 SSD 直接 DMA 到 HBM

      End-to-end results #

      Figure 8: End-to-end TTFT and ITL across workloads

      Paper's Figure 8, verbatim (caption: "End-to-end TTFT and ITL on Llama3-8B across LEval and LooGLE under two vLLM versions...").

      核心发现:(1) vLLM v0.17 加速 compute 后 GDS 的 I/O 瓶颈更凸显,DRAM 相对领先收窄;(2) Tutti 在所有 RPS 下保持最低且最稳 TTFT 曲线;(3) LooGLE 长序列场景 Tutti TTFT 仅为 GDS 的 38%。

      Figure 9: Raw bandwidth of retrieve and store

      Paper's Figure 9, verbatim (caption: "Raw bandwidth of retrieve and store interfaces across varying context lengths.").

      Retrieve 带宽随 sequence length 近线性增长至 25.9 GB/s(2-disk RAID-0),而 GDS 饱和于 11.9 GB/s。Store 受限于 SSD 写入峰值 ~10 GB/s,但仍优于 GDS 7 GB/s。LMCache-DRAM 在 16K tokens 出现碎片导致带宽跌至 8.5 GB/s 的不稳定现象。

      Figure 13: Crossover point analysis — bubble vs compute

      Paper's Figure 13, verbatim (caption: "Decomposition of latency by cache hit rate, highlighting the critical Crossover Point (★) where bubble time begins to exceed compute time.").

      Tutti 将 crossover point 推至 98.3% hit rate——意味着在几乎所有实际工作负载(hit rate < 98%)下,SSD I/O 延迟完全被 compute 掩盖,bubble time 平均仅 25 ms。这是 SSD-backed KV cache 实用化的关键证据。

      Workload characterization #

      Workload regimeTuttiBaseline (GDS)Why
      Short prefix (16K–32K), low concurrency5.8–13.4% better than GDS; matches DRAMGDS adequate but not optimalSlack windows large, I/O easily hidden
      Long prefix (64K–112K), moderate concurrency61.4% TTFT reduction vs GDSGPU bubble >70%Massive I/O volume requires GPU-centric path
      Very high reuse (>96K/128K prefix)DRAM leads by ≤20.6%N/A (GDS OOM at 512K+)Per-layer transfer exceeds slack; raw DRAM latency wins
      Mixed prefill + decode (LEval)2× RPS under SLOGDS violates SLO earlySlack-aware scheduler hides write I/O in decode
      Ultra-long (640K, multi-GPU)1.2 s TTFTGDS: OOMNo staging buffer → no memory pressure

      Evaluation specifics #

      • Baseline versions: vLLM v0.12.0 (Dec 2025) 和 v0.17.0 (Mar 2026); LMCache v0.4.2
      • Fair tuning: baselines 使用各自最优配置(LMCache-DRAM-LW 带 layer-wise pipelining, GDS 带 cuFile)
      • Metric definitions: TTFT = time from request arrival to first output token; ITL = average inter-token latency; throughput = output tokens/hour for cost model

      §6 论证链 #

      StepClaimEvidenceLogic
      1Paged KV layout + SSD = 大量碎片化随机 I/O → GPU stall 70–80%Fig. 2: SSD 和 GDS 配置下 GPU bubble 占比实测 + 因果分析(page-based allocation → fragmentation → CPU I/O overhead)
      2CPU 是瓶颈根因,而非 SSD 带宽不足§2.4: 即使 GDS P2P DMA,CPU 仍在 control path 发起每次 I/ONVMe doorbell/command submission 在 CPU 侧
      3GPU-native object store 消除 data path CPU 开销§3.1: SGL 替代 PRP(31–91× BW gain, Fig. 10); Tensor-Stripe 对齐设计 + 微基准验证
      4GPU io_uring 消除 control path CPU 开销§3.2: ring buffer in HBM, SM partitioning 隔离 I/O架构设计 + §4 端到端验证
      5Slack-aware scheduling 消除 GPU resource contention§3.3: 离线 profiling + 解耦 R/W(Fig. 6 证明混合 R/W 带宽跌 60%)Lookup table 驱动 + 消融(Fig. 13 crossover push)
      6三项设计协同 → SSD-backed ≈ DRAM-backed 性能Fig. 8 端到端 + Fig. 11 TTFT vs prefix length + Fig. 13 crossover全系统集成验证
      7容量无限 + 性能不降 → 成本降低Fig. 14 + Eq. 1: SSD $/GB 比 DRAM 低 100×,throughput 持平数学推导 + 实测

      §7 实现 cross-reference #

      • vLLM KVConnector 集成:~1,500 LoC Python(注册 KV memory block pool, 构建 logical → GPU file 映射)
      • GPU-centric object store + gio_uring:~8,000 LoC C++
      • 接口:retrieve_layer(layer_id, block_ids), store_layer(layer_id, block_ids)
      • SM partitioning 基于 NVIDIA green context API
      • NVMe SQ/CQ 管理基于 GeminiFS 内核模块
      • Mooncake 集成用于 cluster-wide 元数据(空间分配、replica 位置查找)

      具体文件/行号:[实现未公开](论文声明 open-source 但截至撰写未发布代码仓库)

      关键实现细节 #

      1. Pre-allocation 消除运行时开销:NVMe file pool 在 Tutti 启动时预分配所有 extent;P2P mapping table 在 KV cache pool 初始化时一次性计算 SGL 描述符。运行时路径零 allocation。
        1. IOCB batch size = 2048 对齐 H100 SM 调度单元:每个 IOCB 包含 2048 IOCTXs,对应 2 SMs × 64 warps × 32 threads / 2(考虑 register pressure)。这个对齐确保 I/O kernel 恰好占满分配给 I/O Domain 的 SM 资源,避免浪费。
        2. §8 API & usability #

          • User-facing API: 通过 vLLM KVConnector 接口暴露,对上层用户透明(OpenAI-compat API 不变)
          • Config surface: 需要指定 SSD 设备路径、GPU file pool 大小、SM partition 比例;offline profiling 生成 slack lookup table(一次性,复用)
          • Migration cost: 从 vLLM + LMCache-DRAM 迁移需要:(1) 安装 GeminiFS kernel module;(2) 替换 KVConnector 实现;(3) 运行一次 offline profiling。非侵入式——不修改 vLLM 调度器或 attention kernel。

          §9 Adoption & ecosystem #

          • Upstream status: 未合入 vLLM 主线;以 KVConnector plugin 形式集成,跨 vLLM 版本可用
          • Production deployment: 论文未披露生产部署信息
          • Downstream requirements: 需要 NVIDIA green context 支持(H100+);需要 NVMe SSD 支持 SGL(NVMe 1.1+,企业级 SSD 标配);需要 PCIe P2P(CPU 需支持 PCIe ACS bypass)
          • Ecosystem position: 与 Mooncake 配合形成 cluster-level tiered KV cache;与 LMCache 竞争同一生态位

          §10 Deployment context #

          • Serving stage: prefill(主战场:TTFT 优化)+ decode(利用 slack 做异步 store)
          • Concurrency regime: 中高并发(论文测试 0.5–2.0 RPS,约 8–32 并发 long-context requests)
          • Hardware affinity: H100(需 green context 做 SM partitioning);PCIe 5.0 SSD 最佳(带宽上限更高)。对 A100 可能受限于无 green context 的 SM 隔离能力
          • Ecosystem integration: vLLM KVConnector 插件 + GeminiFS kernel module + Mooncake(可选,集群元数据)
          • Migration path: vLLM 用户需 (1) 部署 GeminiFS;(2) 将 LMCache KVConnector 替换为 Tutti;(3) 配置 SSD 路径和 SM partition ratio

          §12 Software → Hardware reverse implication #

          Tutti 属于 hardware-proximal framework:直接操作 NVMe SQ/CQ doorbell、P2P DMA descriptor(SGL vs PRP)、SM 硬件隔离(green context)。

          硬件原语若存在将简化软件

          1. GPU-native NVMe controller:若 GPU 芯片集成 NVMe 端点控制器(或 CXL-attached NVMe),可跳过 PCIe P2P 配置和 doorbell MMIO,direct SGL 发射延迟从 μs 级降至 ns 级。
          2. Hardware SM preemption with I/O priority:当前需手动 green context 隔离 SM;若 GPU scheduler 支持硬件级 I/O 优先级通道(类似 CPU 中断优先级),Tutti 无需静态分区 SM,可动态调度 I/O kernel。
          3. Unified memory with NVMe coherency:若 NVMe 可参与 GPU 统一内存的 coherence domain(类 CXL.mem),则 KV cache 可作为 demand-paged 远端内存,无需显式 retrieve/store 接口。
          4. SSD-side scatter/gather 感知:SSD 控制器原生支持 GPU 地址空间的 scatter-gather(无需 host-side SGL 构建),可进一步消除 CPU 参与的最后一步——SGL 描述符预计算。