Inside vLLM’s New KV Offloading Connector: Smarter Memory Transfer for Maximizing Inference Throughput

发表时间: 2026-01 · Blog post by Or Ozeri, Danny Harnik (vLLM Team at IBM Research) (blog.vllm.ai)

原文: https://blog.vllm.ai/blog/2026-01-08-kv-offloading-connector

作者/机构:Or Ozeri, Danny Harnik (vLLM Team at IBM Research)

速读

一句话结论
本文在 vLLM 中引入了全新的异步 KV 缓存卸载连接器(Offloading Connector),通过重构 GPU 显存布局以最大化底层 DMA 的传输效率,在多并发请求场景下将系统吞吐量提升了最高 9 倍。

要解决什么问题
大语言模型推理的 Prefill(预填充)阶段计算成本极高,通常需要缓存并复用 KV 数据来降低延迟和提升吞吐量。然而,在处理大量并发请求时,GPU 显存极易耗尽。原有的处理机制是:当显存不足时,推理引擎会抢占(preempt)正在运行的请求,并直接丢弃其在 GPU 中的 KV 缓存;当该请求重新调度时,必须从头重新计算 KV 数据,这造成了巨大的算力浪费。为了避免重算,将 KV 缓存卸载到容量更大、成本更低的 CPU 内存(DRAM)是一个理想选择。但原有的 vLLM 卸载方案卡在两个致命瓶颈上。首先是同步阻塞问题:旧版 Connector API 在向外部读写 KV 数据时是同步执行的,数据传输期间整个 vLLM 引擎被完全阻塞,无法并行处理新的请求批次。其次是底层传输效率极低:GPU 与 CPU 之间的数据拷贝若要实现高带宽,必须依赖大块连续内存的传输;但 vLLM 默认的显存分配策略会导致严重的内存碎片化,使得单次传输的物理内存块极小,根本无法发挥硬件总线的真实带宽,导致卸载带来的额外传输开销甚至抵消了免于重算的收益。

怎么做的
核心思路是构建一个完全异步的插件化卸载架构,并从底层重构 vLLM 的 KV 缓存物理显存布局,从而在不占用 GPU 计算核心的前提下,榨干 PCIe 总线的双向传输带宽。该方法由两个关键部件构成。第一个部件是异步卸载连接器(Offloading Connector)。它利用了非阻塞的 API 设计,允许在后台执行 KV 数据的卸载与加载,使得数据传输与 GPU 的模型前向计算完全重叠。在传输机制的选择上,作者放弃了使用自定义 CUDA Kernel(该方法利用 GPU 核心并行拷贝指针,虽对小块内存有效,但会与模型推理争抢计算资源),转而采用基于 cudaMemcpyAsync 的 DMA(直接内存访问)硬件模块。DMA 能够在不增加 CPU 和 GPU 核心负载的情况下实现极高的数据吞吐,但前提是必须传输大块连续内存。这就引出了第二个关键部件:连续化显存布局重构。在原版 vLLM 中,显存按 16 个 Token 为一个逻辑块进行分配。对于多层均匀模型,一个逻辑块的 KV 缓存会被碎片化地切割到各个 Transformer 层中,甚至在某些注意力后端下还会被进一步拆分为单独的 K 块和 V 块。这导致实际物理块大小仅有几 KB 到几十 KB。为了适配 DMA 的特性,作者修改了分配逻辑,将所有层的 KV 数据合并分配为一个连续的物理块。其关键不变量可表示为:

$$ \text{New\_Block\_Size} = \text{Old\_Block\_Size} \times 2 \times \text{num\_layers} $$


通过这一重构,物理块大小从 16KB 级别暴增至 0.5MB 到 2.5MB 级别。在 2MB 块大小下,DMA 的双向传输吞吐量可达 83.4 GB/s,彻底绕开了内存碎片化导致的传输卡点,使得 DMA 成为兼顾高带宽与零计算干扰的最优解。

效果如何
实验在单台配备 NVIDIA H100 80GB GPU、Intel Xeon 处理器和 500GB DRAM 的机器上进行,使用 FlashAttention 后端,禁用 GPU 前缀缓存以纯粹评估 CPU 命中率。对比基线包含三种路线:无 CPU 卸载(代表显存耗尽后纯靠 GPU 重算的基线)、自定义 CUDA Kernel 传输(代表占用 GPU 计算核心换取小块内存传输速度的路线)、以及本文提出的 DMA 传输(代表重构显存布局后的硬件加速路线)。在单请求首字延迟(TTFT)测试中,对于 Llama-3.1-8B-Instruct 模型,从 CPU 加载 KV 缓存相比 GPU 重算,将 TTFT 缩短了 2 倍到 22 倍(取决于 Prompt 长度)。在多并发吞吐量测试中(提交 10000 个 512 Token 的独立请求),随着 CPU 缓存命中率的提升,系统整体吞吐量最高增加了 9 倍。在与 CUDA Kernel 路线的直接对比中,作者故意选用了物理块较小(0.5MB)的 Llama-3.2-1B-Instruct 作为 DMA 的最差场景进行压力测试。结果显示,虽然 CUDA Kernel 在单请求 TTFT 上快了不到 1 毫秒,但在并发吞吐量上,DMA 路线凭借零计算干扰的优势,在 80% 命中率下比 Kernel 路线高出 15%;而在常规大块模型(如 Llama-3.1-8B-Instruct)上,DMA 路线的吞吐量更是比 Kernel 路线高出 32%。该方法的局限在于,目前尚未对混合架构模型(Hybrid models)的显存布局进行优化,且在 0% 缓存命中率的极端情况下,任何卸载机制的额外开销都会导致吞吐量出现轻微下降。

A1 主要贡献

大语言模型(LLM)的推理服务是一项计算复杂度极高的操作,其核心在于计算被称为KV数据的多维数据块。在处理请求的生命周期中,生成用户提示(prompt)响应的第一步是计算与该提示对应的KV值,这一阶段被称为预填充(prefill)阶段。预填充阶段需要为每个提示计算KV值,计算成本极为高昂,通常需要依赖GPU等专用加速硬件才能快速完成。

为了避免重复计算,针对具有相同前缀的提示,系统通常会缓存并复用其KV值。然而,在处理大量并发请求时,GPU内存往往不足以存储所有正在处理的请求所需的KV值。此时,推理引擎可能会抢占(preempt)某个正在运行的请求,并将其KV值从GPU内存中丢弃。当该请求后续被重新调度时,必须重新计算其KV值。

为了解决这一问题并最大化推理吞吐量,本文提出了以下核心贡献:

  1. 引入全新的异步卸载连接器(Offloading Connector):在vLLM中实现了一个可插拔的后端API,支持将KV缓存异步卸载到CPU内存(DRAM)中,从而避免了请求抢占后昂贵的KV重计算开销。
  2. 重构vLLM的GPU内存布局:将原本碎片化的KV缓存布局修改为包含所有层KV数据的连续物理块,使得单块物理内存大小提升了数倍(最高达2MB)。
  3. 优化GPU-CPU传输机制:基于连续的大内存块设计,采用直接内存访问(DMA,即 cudaMemcpyAsync)替代自定义CUDA内核进行数据传输。该设计在保证高传输带宽的同时,极大地减少了对GPU计算核心的干扰,使得并发请求的吞吐量提升了最高达9倍,同时显著降低了首token时间(TTFT)。

A3 背景知识与设计原则

KV缓存复用的核心优势:对于许多应用场景而言,缓存并复用KV值可以带来两个主要优势。首先是改善请求延迟,前提是从缓存中读取数据的速度快于重新计算KV数据的速度;其次是提高单节点吞吐量,因为复用KV数据减少了GPU核心的负载,从而允许系统同时处理更多的并发请求。

无公共前缀场景下的卸载价值:即使对于请求之间没有共享前缀的工作负载,KV缓存卸载依然非常有用。在处理高并发请求导致GPU内存耗尽时,系统必须抢占部分请求。如果在请求被抢占之前,将其KV缓存卸载到容量更大的存储层(如CPU DRAM),就可以在请求恢复时直接加载数据,完全避免重新计算KV值的巨大开销。

选择CPU内存(DRAM)作为卸载目标的原因:本文重点关注将KV卸载到CPU内存中,这一实践具有极高的吸引力,主要基于以下综合因素:

  • 广泛的可用性:CPU RAM在各种部署环境中都广泛存在。
  • 容量优势:CPU RAM的容量通常远大于GPU内存,允许系统维持一个大得多的KV缓存池。
  • 传输性能优异:CPU RAM与GPU内存之间的数据传输具有低延迟和高吞吐量的特性。结合其大容量优势,这使得CPU卸载成为高效处理请求抢占的理想选择。
  • 作为外部存储的理想暂存区:CPU RAM也是进一步将数据卸载到外部存储时的便捷暂存区(staging area),这在外部存储延迟较高的情况下尤为有利。

A2 方法细节

vLLM连接器API的演进与异步化设计
vLLM长期以来一直支持用于读取和写入KV数据的API,并与请求的生命周期深度集成,该API被称为连接器API(Connector API)。在宏观层面上,vLLM在处理任何请求之前都会查询此API,从而允许从外部源导入KV数据;在完成KV数据计算后,vLLM同样会调用此API将新生成的KV值存储到外部目标中。
最初,连接器API是同步执行的,这意味着当vLLM在外部加载或存储KV值时,vLLM引擎会处于阻塞状态,无法并行处理新的请求批次。从vLLM 0.9.0版本开始,连接器API被扩展以支持异步加载和存储KV数据。本文引入的新型卸载连接器(Offloading Connector)正是利用了这一新的异步API来实现KV缓存的卸载。
卸载连接器暴露了一个可插拔的后端API,允许使用任何介质来进行数据卸载。这种API设计极大地简化了添加新卸载后端的过程——开发者基本上只需要定义一个传输函数(transfer function)来实现不同介质之间的KV数据拷贝即可。目前,卸载连接器捆绑了一个CPU后端,从而在vLLM中启用了原生的KV数据CPU卸载功能。

卸载连接器的配置与使用方法
要使用卸载连接器进行CPU卸载,只需在 vllm serve 命令中添加特定的CLI标志。对于即将发布的0.14.0版本(基于PR #24498),配置命令如下:

--kv_offloading_backend native --kv_offloading_size <size_in_GB>

对于较旧的vLLM版本,可以通过以下CLI命令启用CPU卸载:

--kv-transfer-config '{"kv_connector":"OffloadingConnector","kv_role":"kv_both","kv_connector_extra_config":{"num_cpu_blocks": <num_cpu_blocks>}}'

其中 <num_cpu_blocks> 表示为CPU KV缓存分配的CPU块数量。此外,0.14.0版本还将引入进一步的改进,包括允许将抢占的请求从CPU加载回GPU(PR #29870),以及修复卸载与模型计算之间的竞争条件(PR #31341)。

评估GPU-CPU传输技术的两种策略
在定义卸载连接器的后端时,核心组件是传输函数。对于CPU后端而言,该传输函数负责在GPU内存与CPU内存之间双向拷贝数据,目前支持所有兼容CUDA的设备(包括NVIDIA和AMD)。本文对比了两种在GPU和CPU之间拷贝数据的技术方案:

  • 基于DMA的拷贝:使用 cudaMemcpyAsync 函数,该函数利用GPU上的硬件组件DMA(直接内存访问)。DMA专为设备(GPU)和主机内存之间的高吞吐量数据传输而设计。更重要的是,利用DMA执行传输意味着对CPU和GPU计算核心的开销极小。由于传输操作与模型计算是异步并行的,这一特性显得尤为关键。
  • 基于自定义CUDA内核的拷贝:编写自定义内核,利用GPU计算核心并通过裸指针(raw pointers)来拷贝16字节的字(words)。这种方法的优势在于它利用了GPU核心提供的大规模并行性;但其代价是会对GPU核心正在执行的主要计算任务造成严重的干扰。

传输机制的微基准测试与块大小的影响
为了评估DMA的速度及其与自定义CUDA内核的对比,作者创建了微基准测试 gpu_cpu_benchmark。首先测量了单次传输1000个块的吞吐量,块大小从4KB到16MB不等。测试结果表明,DMA表现优异,但前提是必须处理较大的物理连续块。对于较小的块,自定义内核能实现显著更高的吞吐量,尽管其结果方差较大且包含更多噪声。
单向GPU到CPU传输吞吐量 (NVIDIA H100, 单次1000个blocks的传输)
单向CPU到GPU传输吞吐量 (NVIDIA H100, 单次1000个blocks的传输)
接着,作者测试了双向传输吞吐量,即同时发起一个读传输和一个写传输。在此测试中,固定块大小为2MB,并调整双向传输数据量的比例。对于这两种拷贝机制,当双向传输的数据量大致相同时,均能达到峰值吞吐量。然而,尽管在单向传输中两者都能达到约50GB/s,但在双向传输中结果出现了差异:DMA达到了83.4 GB/s,而自定义内核仅达到68.5 GB/s。

重构vLLM的内存布局以适配DMA传输
上述测试引出了一个关键问题:vLLM实际使用的有效块大小是多少?默认情况下,vLLM以token块(默认每块16个tokens)为单位分配GPU内存。实际的物理布局取决于所使用的注意力后端(如FlashAttention、FlashInfer等)以及正在提供服务的模型。
对于当前最常见的多层统一模型(uniform models),vLLM原本会为每一层分配其独立的KV缓存。因此,一个逻辑块的KV缓存会被物理分割成 num_layers 个碎片块(每层一个)。此外,根据不同的注意力后端,每层的块可能还会被进一步分割为2个子块(一个用于K缓存,一个用于V缓存)。这种碎片化对模型计算性能没有影响,但对KV卸载却是灾难性的,因为它导致了极小的有效物理块大小。
为了解决这个问题,作者在vLLM中提交了一项更改(PR #27743),修改了KV缓存布局,创建了一个包含所有层KV数据的连续物理块。这一改变有效地将物理块大小增加了 2 * num_layers 倍,进而使卸载连接器的吞吐量提高了一个数量级。
下表总结了当前常用模型在旧布局(0.11.0版本)与新布局(0.12.0版本)下的物理块大小对比(假设vLLM使用16 tokens块):

Model Old block size New block size
deepseek-ai/DeepSeek-R1-Distill-Qwen-32B (tensor_parallel_size=2) 16 KB 2 MB
deepseek-ai/DeepSeek-V2-Lite-Chat (GPU block size=64) 72 KB 1.9 MB
meta-llama/Llama-3.1-8B-Instruct 32 KB 2 MB
meta-llama/Llama-3.2-1B-Instruct 16 KB 0.5 MB
meta-llama/Llama-3.1-70B-Instruct 8 KB 1.25 MB
mistralai/Mistral-7B-Instruct-v0.2 32 KB 2 MB
mistralai/Mistral-Small-24B-Instruct-2501 32 KB 2.5 MB
Qwen/Qwen2.5-3B-Instruct 8 KB 0.56 MB
Qwen/Qwen3-0.6B 32 KB 1.75 MB
Qwen/Qwen2.5-7B-Instruct 16 KB 0.87 MB
Qwen/Qwen3-4B-Instruct-2507 32 KB 2.25 MB
Qwen/Qwen2.5-1.5B-Instruct 8 KB 0.44 MB
Qwen/Qwen3-8B 28 KB 1.97 MB
Qwen/Qwen3-1.7B 32 KB 1.75 MB
Qwen/Qwen3-32B (tensor_parallel_size=2) 16 KB 2 MB

如表所示,新的vLLM KV缓存布局产生的物理块大小约为0.5-2 MB,而旧布局仅为几KB。结合GPU-CPU微基准测试的数据,在新的内存布局下,基于DMA的传输方法预期将具有与自定义内核方法相当(或略差,取决于具体模型)的传输性能,但却能大幅降低对GPU核心的干扰。

A4 实验环境

为了全面评估vLLM的CPU卸载性能,实验采用了以下软硬件配置:

  • 硬件配置:

    • CPU:Intel Xeon SapphireRapids 2.1Ghz(限制为8核)。
    • GPU:单张 NVIDIA H100 80GB HBM3。
    • 内存:500GB DRAM。
  • 软件与系统配置:

    • 操作系统:单一 Ubuntu 24.04.1 LTS 容器。
    • 内核版本:Kernel 5.14.0-427.81.1.el9_4.x86_64。
    • CUDA版本:12.9。
    • vLLM版本:提交哈希值为 2a1776b7ac4fae7c50c694edeafc1b14270e4350。
  • 模型与运行参数:

    • 使用 Flash Attention 作为注意力后端。
    • 禁用了GPU前缀缓存(以便准确评估CPU缓存命中率)。
    • GPU和CPU的块大小均设置为16 tokens。
    • 禁用了编码/解码(De/Tokenization)过程。
  • 基准测试代码:实验使用的基准测试代码已开源于 kv_offload_benchmark.py。

A4 实验结果

实验一:CPU卸载对单请求延迟(TTFT)的提升

  • 实验内容:测量处理单个预填充请求的延迟,将从CPU加载KV缓存的时间与GPU重新计算KV值的时间进行对比。模型采用 Llama-3.1-8B-Instruct。
  • 实验结果:从CPU加载KV值能够将首token时间(TTFT)显著降低,降幅达到2倍至22倍(取决于提示词的长度)。
  • 分析结论:由于卸载过程(将KV数据从GPU拷贝到CPU)是异步进行的,用户请求的完成无需等待传输结束,因此卸载延迟不会直接暴露给用户。这意味着使用卸载连接器对缓存未命中时的TTFT几乎没有负面影响。在vLLM 0.12.0版本中得益于物理块大小的优化,TTFT实现了最高4倍的缩减。
    单请求TTFT (Llama-3.1-8B-Instruct, NVIDIA H100)

实验二:CPU卸载对并发请求吞吐量的提升

  • 实验内容:提交包含10,000个唯一请求(每个请求512个tokens)的批处理,在不同CPU缓存命中率下测量系统处理这些请求所需的总时间(排除CPU缓存预热时间),并推导出以 token/s 为单位的吞吐量。为了专注评估CPU缓存的效果,实验未利用GPU缓存。
  • 实验结果:吞吐量随着CPU KV缓存命中率的提高而线性增加。最高命中率下,整体吞吐量提升了高达9倍。
  • 分析结论:尽管针对512 tokens的提示词,TTFT仅下降了2倍,但吞吐量却提升了9倍。这有力地证明了KV缓存卸载的最大收益在于最大化系统整体吞吐量。在vLLM 0.12.0版本中,吞吐量实现了最高5倍的额外增长。
    并发请求吞吐量 (Llama-3.1-8B-Instruct, NVIDIA H100, 10000个512 tokens的prefill请求)

实验三:端到端拷贝方法对比(DMA vs. 自定义内核)- 单请求TTFT

  • 实验内容:对比官方主线版本(基于DMA传输)与补丁版本(基于自定义内核传输)。为了进行最严格的压力测试,作者刻意选择了对卸载连接器而言最差场景(worst case scenario)的模型——Llama-3.2-1B-Instruct,其物理块大小仅为0.5 MB。
  • 实验结果:在单请求基准测试中,自定义内核产生了略好的TTFT。对于1K tokens的提示词,差异不到1毫秒;对于90K的超长提示词,差异最大约为15毫秒。
  • 分析结论:这一结果符合前文GPU-CPU微基准测试在0.5 MB块大小下的预期。对于具有更大物理块大小的模型,这两种变体在TTFT上的表现基本相同。
    单请求TTFT (Llama-3.2-1B-Instruct, NVIDIA H100)

实验四:端到端拷贝方法对比(DMA vs. 自定义内核)- 并发吞吐量

  • 实验内容:在与实验二相同的并发负载(10,000个512 tokens请求)下,对比DMA与自定义内核的吞吐量表现(模型同为 Llama-3.2-1B-Instruct)。
  • 实验结果:DMA实现了比自定义内核更高的吞吐量。在0%命中率时,DMA的吞吐量优势约为5.5%;在80%命中率时,优势扩大至约15%。
  • 分析结论:自定义内核方法在执行数据拷贝时占用了GPU核心,从而干扰了正常的模型计算。在0%命中率时,自定义内核方法的吞吐量甚至比完全不使用CPU卸载还要低6%。在100%命中率时,由于CPU加载期间没有并行的模型计算,两种方法的差距随之缩小。需要强调的是,上述结果是基于DMA的最差情况模型得出的。对于具有更大物理块大小的主流模型(如 Llama-3.1-8B-Instruct),DMA在保持相同TTFT的同时,其吞吐量比自定义内核高出多达32%。
    并发请求吞吐量 (Llama-3.2-1B-Instruct, NVIDIA H100, 10000个512 tokens的prefill请求)

A5 结论

本文详细介绍了vLLM中新引入的原生KV卸载功能。通过开发支持异步处理的卸载连接器,并将其与CPU DRAM深度结合,系统能够有效应对高并发场景下的请求抢占问题。研究团队通过重构vLLM的GPU内存布局,将碎片化的KV缓存合并为连续的大容量物理块,成功使得低开销的DMA(直接内存访问)传输技术在性能上全面超越了传统的自定义CUDA内核方案。实验证明,该方案不仅能将单请求的首token时间(TTFT)降低2至22倍,更能在高并发工作负载下将系统整体吞吐量最大化提升至9倍,同时完美避免了数据拷贝对GPU计算核心的干扰。

未来工作展望:
研究团队将继续增强vLLM的原生KV卸载功能。下一个重要里程碑是使CPU KV缓存能够作为中间层(intermediate tier),进一步支持向外部存储介质的卸载。团队将始终把系统的正确性与性能作为最高优先级,并鼓励社区在即将发布的版本中进行测试与反馈。