LMCache: An Efficient KV Cache Layer for Enterprise-Scale LLM Inference

发表时间: 2025-10 · arXiv:2510.09665 (preprint)

原文: https://arxiv.org/abs/2510.09665

作者/机构:Yuhan Liu, Jiayi Yao, Yihua Cheng, Yuwei An, Xiaokun Chen, Shaoting Feng, Yuyang Huang, Samuel Shen, Rui Zhang, Kuntai Du, Junchen Jiang (Tensormesh Inc., 芝加哥大学)

速读

一句话结论 LMCache 构建了一个独立于推理引擎的高效 KV Cache 管理与传输层,通过大块批处理和计算通信流水线技术,在多轮对话和长文本场景下实现了最高 15 倍的吞吐量提升和 2 倍以上的首字延迟降低。

要解决什么问题 随着长上下文和前缀复用(如系统提示词、RAG 文档)的普及,KV Cache 的体积已远超单机 GPU 显存容量,必须将其卸载到 CPU 内存或远端存储,并在不同 GPU 节点间传输(例如分离 Prefill 和 Decode 阶段以避免计算相互干扰,这就要求将 Prefill 节点生成的缓存高速传递给 Decode 节点)。原有的做法卡在底层 I/O 机制上:现代推理引擎(如 vLLM 和 SGLang)为了优化显存碎片,普遍采用 PagedAttention 机制,将 KV Cache 切分为 16KB 到 64KB 的离散小页。当需要跨设备传输这些非连续的小内存块时,极小的传输粒度根本无法跑满 PCIe 或网络带宽(通常需要达到兆字节级别才能打满带宽),导致严重的 I/O 阻塞。此外,推理引擎的底层算子迭代极快,频繁改变显存布局,导致强耦合的缓存管理代码极易失效;且上层路由调度器缺乏统一的 API 来感知和调度全局的 KV Cache 分布。

怎么做的 LMCache 的核心思路是将 KV Cache 从推理引擎的内部状态剥离出来,作为一个独立的一等公民数据结构,在 GPU、CPU、磁盘和网络之间进行分层管理和高效流转。为了绕开离散小页带来的 I/O 带宽瓶颈,LMCache 引入了基于中间流式缓冲区的批处理机制。在卸载时,它先用定制的 CUDA Kernel 将分散的页聚合到一块连续的 GPU 缓冲区中,聚合成更大的数据块(默认 256 个 Token 的大小),再通过 DMA 引擎一次性传输到底层存储;加载时则反向拆分。为了掩盖传输延迟,LMCache 设计了逐层流水线,为计算和数据搬运分配独立的 CUDA Stream。当引擎正在计算第 $i$ 层时,第 $i+1$ 层的 KV Cache 正在被异步预取到 GPU 缓冲区中。为了最小化异构存储间的冗余拷贝,系统引入了零拷贝引用计数机制,当同一份缓存需要同时写入本地磁盘和远端存储时,引用计数 $C_{ref} = \sum \text{destinations}$,每次写入完成递减,归零后释放。同时,针对 GPU 空闲页设计了动态卸载策略,通过维护三个指针来控制后台复制进度:空闲区起始指针 $P_{start}$、已卸载指针 $P_{current}$ 和计划卸载终点指针 $P_{end}$,系统必须时刻满足不变量:

$$P_{start} \le P_{current} \le P_{end}$$

其中 $P_{end} - P_{current}$ 定义了正在进行 CPU 备份的冗余窗口大小,窗口越大则新请求分配显存时被阻塞的概率越低,但会增加瞬时内存压力。在工程架构上,LMCache 抽象出了一套标准化的 KV Cache 连接器,在调度器层面拦截 Token 匹配逻辑,在模型执行器层面注入层级加载与卸载的 Hook,从而彻底解耦了缓存层与 vLLM 等后端引擎的演进。此外,它还提供了一套全局控制器 API,允许上层应用主动执行缓存的查找、固定、迁移和压缩。

效果如何 实验在 H100 GPU 集群上搭建,测试了 Llama-3.1-8B/70B、Qwen2.5-Coder-32B 等模型,涵盖单机 CPU 卸载、远端存储共享和 Prefill-Decode 分离(通过 NVLink 连接)三种场景。对比的基线方法包括:仅使用 GPU 显存的纯 vLLM(代表传统不卸载路线)、使用 vLLM 原生 CPU 卸载机制的版本(代表逐页传输路线)、SGLang 的原生卸载方案,以及两种闭源的商业推理 API 方案。在模拟多轮文档问答(10K 上下文)的测试中,LMCache 相比原生 vLLM CPU 卸载方案,将首字延迟降低了 1.9 到 8.1 倍,并在相同延迟下支撑了 2.3 到 14 倍的并发吞吐量;在基于企业真实流量轨迹的测试中,同样将首字延迟降低了 3.7 到 6.8 倍;在 Prefill-Decode 分离场景下,相比 vLLM 原生方案,平均首字延迟降低了 1.53 到 1.84 倍。作者也坦诚了该方案的局限与代价:当网络带宽极低(如 32Gbps)时,只有当输入上下文超过 256K Tokens 时,从远端拉取缓存的速度才会快于直接重新计算;此外,工业界常用的上下文截断策略会破坏前缀的完整性,导致前缀缓存命中率直接腰斩,这是纯系统层优化无法解决的业务逻辑冲突。

主要贡献

传统上,KV缓存一直存储在GPU内存中,以加速大型语言模型(LLM)推理的解码阶段。然而,随着上下文的增长和推理引擎的发展,越来越需要将KV缓存移出GPU设备,以实现跨不同查询和推理引擎的缓存重用。真实世界的使用统计数据证实了这一趋势:随着时间的推移,用户存储的KV缓存总量快速增长,已经远远超出了GPU内存的容量。尽管存在这种需求,但目前仍缺乏一种高效的解决方案来卸载和传输KV缓存。

为了解决这一问题,本文提出了LMCache,这是首个也是迄今为止最高效的开源KV缓存解决方案。它能够将现代LLM引擎(如vLLM和SGLang)生成的KV缓存从GPU内存中提取并存储出来,并在不同引擎和查询之间共享。LMCache同时支持缓存卸载(跨查询的前缀重用)和预填充-解码(PD)解耦(跨引擎/GPU的缓存传输)。

LMCache的主要贡献包括:
1. 高度优化的KV缓存数据移动:通过批处理数据移动操作、计算与I/O流水线技术提供支持。
2. 模块化的KV缓存连接器组件:将LMCache与快速演进的推理引擎解耦。
3. 一等公民控制API:提供诸如固定(pinning)、查找、清理、移动和压缩等API,用于在GPU、CPU、存储和网络层之间灵活地编排缓存。

实验评估表明,将LMCache与vLLM结合使用,在多轮问答和文档分析等工作负载中,吞吐量可提升高达$15 \times$。LMCache在企业环境中的大规模采用也提供了宝贵的见解,例如:从远程存储获取KV缓存对预填充延迟有出乎意料的好处;而工业界广泛应用的上下文截断技术会使前缀缓存命中率大幅降低一半。

图1:上图:随着时间的推移,越来越多的用户正在使用LMCache。中图:LMCache被用于存储更大规模的KV缓存。下图:LMCache的Docker镜像拉取次数持续增加。
图1:上图:随着时间的推移,越来越多的用户正在使用LMCache。中图:LMCache被用于存储更大规模的KV缓存。下图:LMCache的Docker镜像拉取次数持续增加。

背景知识与设计动机

KV缓存的作用。最初引入KV缓存是为了加速单个推理查询,它通过将输入Token和先前生成的Token的注意力状态(以$K$和$V$张量的形式)直接存储在GPU内存中来实现。KV缓存有效地存储了该查询中迄今为止看到的每对Token之间的注意力信息。简而言之,它是知识的一种LLM原生表示形式。

跨查询共享的趋势。如今,上下文变得越来越长,人们也开始利用背景知识来增强推理。鉴于这种趋势,在不同的用户查询之间共享KV缓存以减少长上下文或背景知识的冗余计算变得非常流行。

图2:LMCache同时支持上下文缓存(KV缓存卸载和跨查询共享)以及PD解耦(KV缓存的跨引擎传输)。
图2:LMCache同时支持上下文缓存(KV缓存卸载和跨查询共享)以及PD解耦(KV缓存的跨引擎传输)。

KV缓存规模超出GPU内存。尽管在所有传统的LLM推理系统中,KV缓存一直保存在GPU内存中,但根据用户自愿开启的使用追踪器收集的真实世界使用统计数据,我们观察到所需的KV缓存规模现在已经远远超出了GPU内存容量。图3显示了过去五周内KV缓存大小的每周增长情况,分为适合GPU内存的缓存(绿色)和超出GPU内存容量的缓存(蓝色)。随着时间的推移,不再适合GPU内存的KV缓存部分显著增加,这表明仅靠GPU内存不足以存储所有缓存。为了实现跨查询的KV缓存重用(尤其是那些在重用前很久生成的缓存),必须将KV缓存移出GPU内存,例如将其卸载到CPU内存或其他存储层。

图3:KV缓存大小的每周增长情况,包括适合GPU内存的部分和超出GPU内存的部分。
图3:KV缓存大小的每周增长情况,包括适合GPU内存的部分和超出GPU内存的部分。

每个Token的重用率大幅增加。我们还观察到,随着时间的推移,每个Token的重用次数大幅增加。如图4左侧所示,我们绘制了GPU内存之外被重用的Token与所有已存储Token之间的比例(排名前10的用户)。我们将此比例称为每个Token的重用率。在过去几周中,每个Token的重用率显著增长,这表明无法放入GPU内存的Token正越来越频繁地被推理重用。这意味着越来越多的Token需要被重新加载回GPU内存。图的右侧显示了过去一周不同用户的每个Token重用率的分布情况。超过$19\%$的用户对已存储的Token重用了1.5次以上,这表明用户在存储Token后多次访问它的趋势。

图4:左图:顶级用户的平均每个Token重用率。右图:不同用户之间平均每个Token重用率的分布。
图4:左图:顶级用户的平均每个Token重用率。右图:不同用户之间平均每个Token重用率的分布。

需要高效的KV缓存层。从上述真实世界部署中收集的统计数据观察中,我们发现了KV缓存的两个重要趋势。首先,无法简单放入GPU内存的KV缓存不断增长,这可能是由于上下文长度的增加或用户流量的增大。其次,存储在GPU内存之外的每个Token的重用率随着时间的推移也在增加。这两个趋势都表明我们需要将KV缓存移出GPU内存。具体而言,在当前的工业界中,存在两种将KV缓存移出GPU的场景:
1. 上下文缓存(即跨查询的KV缓存重用)持久化来自一个查询的KV缓存段,并将其重用于共享公共前缀的后续查询。例子包括在多个查询中保持不变的文档(块)分析,以及具有固定系统提示或长前言的多轮对话。前缀缓存减少了预填充阶段的冗余计算,直接降低了TTFT(首字延迟)和每个查询的GPU小时数(Chen 等人 [5];Gao 等人 [9] 等)。
2. 预填充-解码(PD)解耦(即跨引擎的KV缓存传输)将推理过程拆分为预填充阶段(处理整个输入提示)和解码阶段(自回归生成Token),分布在不同的GPU或节点上。这种方法通过最大化解码速度而不被预填充阶段中断,从而降低了尾部延迟。

Message SizeTransfer Throughput
64KB4GBps
256KB13GBps
1MB30GBps
10MB46GBps
16MB49GBps
100MB49GBps

表1:使用RCCL传输库时,传输消息大小与实现的传输吞吐量的关系。

分页内存下的I/O低效问题。KV缓存的存储和传输过去依赖于PyTorch序列化(torch.save / torch.load)或原始的张量复制,典型的传输速度仅为亚1GB/s级别。这些方法引入了不小的延迟开销,尤其是在处理像KV缓存这样的大型数据结构时,并且缺乏与各种存储设备(本地或远程)的零拷贝支持,导致了额外的CPU-GPU数据复制。最近的高吞吐量推理引擎(如vLLM [18] 和SGLang [35])使KV缓存的存储和传输变得更加困难。它们采用分页注意力内存,将注意力缓冲区划分为较小的固定大小页面(通常为16-64 KB)。由于KV缓存的页面并不总是连续的,分页内存架构急剧增加了持久化或传输KV缓存所需的小尺寸I/O操作的数量。传输这种小块数据已知会导致网络带宽利用率不足并降低吞吐量。

与快速发展的推理引擎的兼容性。随着AI的广泛使用,新的LLM和硬件加速器不断快速推出。在2025年,平均每4天就会发布一个著名的LLM。作为回应,推理引擎必须以同样快的速度发展。每次为了适应新模型或硬件的更新,通常都会改变GPU内存分配,进而改变KV缓存接口。例如,当vLLM采用产生不同维度KV缓存的新注意力内核时,必须更新KV缓存库以将新内核的输出KV缓存格式转换为与KV缓存库兼容的格式。鉴于推理引擎的快速变化,跟上这些频繁的变化需要付出巨大的努力。

缺乏管理API。随着KV缓存成为LLM推理后端中的一等公民,除LLM推理引擎外的各种组件以及ML运维团队,都需要以感知KV缓存的方式做出决策。然而,如果没有一个统一的管理接口来定位、驱逐、固定或压缩缓存,这些上层模块就无法做出明智的放置或驱逐决策。这导致了缓存利用率低下、存储重复和驱逐策略不可预测。例如,推理查询路由器需要知道KV缓存的位置,以便将查询路由到已经在本地(如CPU内存中)持有匹配前缀Token的KV缓存的实例。

现有解决方案的局限性。虽然存在几种KV缓存处理机制,但没有一种能完全解决上述挑战。推理框架(如vLLM Production Stack、Dynamo等)侧重于在Kubernetes上轻松部署,虽然支持KV缓存,但缺乏跨节点传输优化。KV缓存存储层(如Mooncake、Redis)提供分布式对象存储或缓存,但它们缺乏在推理引擎之间高效频繁地跨不同存储层移动小张量的“粘合”层,或者与特定的推理框架紧密耦合。专有实现(如Fireworks AI)与闭源服务栈绑定。研究源码通常基于面向研究的框架(如HuggingFace),尚未完全达到企业级就绪状态。

方法细节

LMCache架构定位。LMCache通过一个统一的、高性能的KV缓存层来解决上述挑战,该层能够为分页内存推理引擎进行高效的存储、移动和KV缓存的显式管理,使前缀缓存和PD解耦在企业规模上变得实用。作为一个KV缓存层,LMCache位于LLM推理引擎和异构存储/网络设备之间。它的目标是为KV缓存的移动和管理提供一个标准化的、高性能的基础层,同时保持与快速发展的推理框架(如vLLM和SGLang)的兼容性。

图5:LMCache位于LLM推理引擎与异构存储/网络设备之间。
图5:LMCache位于LLM推理引擎与异构存储/网络设备之间。

端到端系统工作流。图6展示了端到端的系统。下面,我们将走查两个示例工作流:存储和检索KV缓存。

图6:LMCache的端到端系统工作流。
图6:LMCache的端到端系统工作流。

存储工作流。当一个新查询到达时,它首先通过KV连接器,连接器准备元数据,例如分词后的输入提示和相关页面的GPU内存地址。然后查询进入Token处理器,处理器确定有多少新Token尚未在后端中并需要被存储。最后,存储管理器通过传输通道(处理数据传输逻辑)将这些新Token的KV缓存保存到后端。

检索工作流。当一个查询需要从后端加载KV缓存时,它同样从KV连接器开始准备元数据。Token处理器识别后端中已经存在的前缀匹配Token的数量。接着,事件管理器检查之前是否见过相同的查询ID。如果是,则缓存的内存地址已被追踪,可以直接返回给GPU连接器,由其将KV缓存加载回GPU内存。事件管理器还会启动异步的逐层加载事件。如果查询ID是新的,它会被转发给存储管理器,以查找已存储KV缓存的CPU内存地址。

查找工作流。当一个查询需要检查后端是否存在特定Token的KV缓存时,诸如路由器等更高层的组件会查询缓存控制器。缓存控制器维护一个Token池,记录当前存储在KV缓存后端的所有Token。每当一个LMCache实例存储或驱逐一个KV缓存时,实例内部的LMCache工作进程就会用新状态更新Token池。这确保了Token池始终拥有后端Token的最新信息。

性能优化的三大挑战。LMCache的一个重要方面是提高跨设备移动KV缓存的效率。在企业级LLM推理中,LMCache解决了三个关键挑战:现代LLM推理引擎以页面粒度管理KV缓存,这些通常为20 KB–63 KB的小单元对于传输来说效率低下;KV缓存传输通常需要与LLM推理并发运行,这会引入延迟和CPU开销;大量查询生成了海量的KV缓存,在任何存储设备上复制它们都会浪费空间并引入复制开销。

可配置的块大小。为了解决小KV缓存单元导致的I/O低效问题,LMCache不以页面级别传输KV缓存,而是将来自多个层的多个页面组合成更大的块,默认大小为每块256个Token。这是通过一个中间的流式GPU缓冲区实现的。对于存储,首先使用定制的CUDA内核将KV缓存从分散的分页GPU内存复制到连续的流式缓冲区中,然后通过DMA引擎以块(而不是单个页面)的粒度集体卸载到较低层的存储(例如CPU内存)。对于加载,首先使用DMA引擎将块从存储层检索到GPU缓冲区中,随后使用CUDA内核将其拆分到分页内存中。

并行的存储/加载操作。LMCache支持跨多个存储层(包括本地CPU DRAM或磁盘、远程CPU DRAM或磁盘以及对象存储)并行存储和检索KV缓存。LMCache的存储和加载API接受多个源和目标设备,从而实现跨异构链路的并发数据移动。此外,当互连支持全双工通信(如PCIe)时,这些操作可以并行执行。

延迟的解码KV缓存存储。LMCache还支持在解码期间存储新生成的KV缓存。LMCache不是立即卸载每个Token的KV缓存(这种朴素的方法会触发频繁的小规模写入),而是缓冲KV缓存,并在生成了预定义数量的Token(即一个块)后执行批处理存储。这种基于块的延迟存储策略减少了写入频率,最小化了I/O开销,并显著提高了整体存储吞吐量。

层级流水线(计算与I/O重叠)。LMCache通过层级流水线将KV缓存传输与推理计算重叠。具体来说,它为每一层内的推理计算和数据移动分配独立的CUDA流。例如,在对第一层执行推理之前,其KV缓存被加载到GPU缓冲区并转换为页面。当第一层正在运行推理时,第二层的KV缓存被异步地获取到缓冲区中并进行类似的转换。这种设计确保只需要一个固定大小的GPU缓冲区(其大小为单层KV缓存的大小),同时实现了数据传输与计算之间的重叠。

异步计算与预取。在许多场景中,推理调度器接纳查询的时间与推理实际需要该查询的KV缓存的时间之间存在时间差。LMCache利用这个空闲时间间隔,将排队查询的KV缓存从较慢的存储层预取到较快的存储层(例如,从远程磁盘预取到本地CPU内存或GPU内存)。因此,当实际的推理计算开始时,所需的KV缓存可以直接从更快的存储层加载或使用,从而显著减少了加载延迟。

零拷贝操作(最小化数据拷贝)。KV缓存移动的朴素实现会在每个传输步骤创建额外的数据副本。LMCache通过仅维护所需的最小副本数来避免这种情况。当同时将KV缓存传输到多个设备时,LMCache通过引用计数器最小化数据重复。每完成一次读取或写入,计数器就会递减,一旦计数达到零,数据就会被释放。这种设计确保数据在并发的读写操作中共享,而无需不必要的复制。

动态卸载机制。现代推理引擎(如vLLM)在GPU内存中维护一个空闲页面池。LMCache不是将所有空闲页面复制到CPU内存,而是仅复制一个子集。该机制使用三个指针实现:Start(GPU内存中空闲页面区域的起始地址)、Current(已卸载到CPU内存的空闲页面的索引)、End(计划卸载的空闲页面的结束地址)。

图7:LMCache中动态卸载的图示。
图7:LMCache中动态卸载的图示。

动态卸载的四种状态。如图7所示,动态卸载有四种状态:状态#1(初始化)中start和current指针重叠。状态#2(进行中)中current指针向end指针移动。状态#3(查询到达)中当新查询获取了一些空闲页面时,end指针向前移动分配的页面数。状态#4(稳定状态)中current指针与end指针重叠,表明所有计划的页面都已复制。一个关键的权衡是:复制的页面数越少,复制比例越低,但分配停顿的可能性就越大。

解耦KV缓存管理的必要性。现代LLM推理引擎发展迅速。支持新架构通常需要对推理引擎进行不小的修改(如添加对滑动窗口注意力的支持)。这些代码更改频繁地改变了内部管理KV缓存的方式,使得LMCache无法以临时的方式进行适应。为了解决这一挑战,LMCache引入了一个标准化的KV缓存连接器接口,将KV缓存管理与推理引擎后端解耦。

API设计目标。关键的设计目标包括:最大的灵活性(启用尽可能多的KV缓存操作);vLLM原生(符合vLLM的设计方向,如严格的调度器-工作节点分离);对树外连接器友好(无需修改vLLM端代码即可集成);最小的API级别开销(不引入API级别的进程间通信等开销)。

连接器API的两个接口集。连接器API包含两组接口:1)调度器接口,在这里来自连接器的额外缓存命中Token被视为vLLM中正常的预取缓存Token,直接影响调度决策;2)模型运行器接口,我们在模型执行前后以及注意力计算前后添加了钩子,以支持大块KV缓存卸载和逐层KV缓存卸载。

Function nameDescription
get_num_new_matched_tokens(query) → Optional[matched_tokens]Returns the number of cache-hit tokens found in LMCAcHE 's backend. Returns None if the LMCAcHE decides to let vLLM process other requests first and put this request back to waiting queue.
update_state_after_allc(query, blocks, num_external_blocks)Updates whether a query needs to transfer KV cache from LM- Cache's backend.
build_connector_meta(scheduler_output) → kv_connector_metadataBuilds metadata for KV cache transfers between LMCache's back- end and GPU memory, including GPU memory addresses for KV cache pages.
start_load_kv(kv_pointers)Starts loading KV cache from lower-tier storage into GPU mem- ory before LLM inference begins.
wait_load_kv(kv_pointers, layer_id)Synchronizes on KV cache loading to ensure data is available when computation requires it.
start_store_kv(kv_pointer) wait_store_ kv(kv_pointer, layer_id) Starts offoading KV cache to lower-tier storage after computation.
Synchronizes on KV cache storing to ensure the KV cache for the current layer is off oaded.

表2:LMCache连接器中的函数。

查询到达时的调度器交互。当查询到达时,调度器首先调用get_num_new_matched_tokens查询LMCache以查看后端的缓存命中Token。如果LMCache决定让vLLM先处理其他请求并将当前请求放回等待队列,该函数可以返回None。然后update_state_after_alloc函数根据匹配的Token信息决定vLLM中的每个页面是否需要从外部存储加载。如果命中大于零,则调用build_connector_meta函数准备必要的元数据。

层级流水线下的模型运行器交互。一旦查询到达模型运行器,在层级流水线的情况下,调用start_load_kv开始将第一层的KV缓存加载到GPU内存。在每一层计算开始前,调用wait_load_kv同步该层的KV缓存加载,并启动下一层的加载。计算后,调用wait_store_kv等待上一层的KV缓存完成存储,然后调用start_store_kv开始存储新生成的KV缓存层。

非层级流水线下的模型运行器交互。在非层级流水线的情况下,在第一层推理开始之前,调用start_load_kv以阻塞方式将整个KV缓存加载到GPU内存。推理将在KV缓存被放置到正确的GPU内存分页地址后发生。当前调度迭代的推理完成后,调用start_store_kv同步将生成的KV缓存存储到较低层的存储中。

控制器的两层架构。LMCache作为一个分布式缓存系统运行,围绕一个集中的KV缓存控制器构建,负责全局元数据管理、缓存操作和请求路由。控制器由两层组成:一个集中的控制器管理器(作为独立进程运行并作为全局协调点)和每个实例的工作进程(与每个对等的LMCache实例共存,处理本地操作或向管理器发出全局请求)。

Internal APIsDescription
batched_admit/batched_evict(hashes, inst_id, device)Send the KV admission/eviction messages from an LMCACHE in- stance to the controller manager.
batched_p2p_lookup(hashes) → list[inst_id, device, hit_chunks]Lookup peer KV cache existence from an LMCAcHE instance based on the the given hashes.
External APIs lookup(tokens) → list[inst_id, device, hit_tokens]Description
move((src_inst_id, src_device), (dst_inst_id, dst_device), tokens)Lookup the global KV cache existence of the given tokens. Moves the KV cache of the given tokens from source location (src_inst_id, src_device) to destination location
clear(tokens, inst_id, device)(dst_inst_id, dst_device). Clears the KV cache for corresponding tokens from the storage
pin/unpin(tokens, instance, storage_device)device device in instance inst_id. Pins/unpins the KV cache for corresponding tokens at location (inst_id, device).
compress/decompress(tokens, instance, device, method)Compresses/decompresses the KV cache for the corresponding tokens at location (inst_id, device) with a specified compres- sion/decompression method.

表3:LMCache控制器中的API。

KV缓存感知路由。每个LMCache实例通过batched_admitbatched_evict接口向控制器管理器报告其缓存接纳和驱逐决策。管理器汇总这些更新并维护所有实例间KV缓存状态的全局内存视图。当路由器调用lookup(tokens)时,控制器查询其内存中的全局状态,并返回一个(instance_id, storage_device, hit_tokens)列表。

KV缓存迁移。当持有KV缓存的实例即将缩容或需要负载均衡时,管理器通过调用move((src_inst_id, src_deivce), (dst_inst_id, dst_deivce), tokens) API处理迁移。源实例将尝试与目标建立连接(如果不存在),并将指定的KV缓存从源存储设备传输到目标位置。

P2P KV缓存共享。发生本地缓存未命中时,实例的本地工作进程可以通过batched_p2p_lookup查询集中的控制器管理器。管理器将返回命中块的数量和持有这些块的位置。实例可以选择从具有最大命中块的对等方加载KV缓存。

KV缓存清理与其他API。应用程序在切换模型或回收内存时可以清理缓存。收到clear(tokens, inst_id, location)调用后,管理器将操作分派给对应的实例以移除关联的KV缓存。用户还可以调用compress/decompress(tokens, inst_id, device, compression_method)pin/unpin(tokens, inst_id, device)来根据需要显式管理特定位置的KV缓存。

实验环境

Scenario AcronymSingle-nodeNetwiork
CPU Off loadSingle-nodeN.A.Single-nadng
Central StorageSingle-nodeEthernet
PDSingle-nodeNVLinkDisagregaion

表4:评估场景设置。

实验结果

单节点CPU卸载。在模拟聊天机器人文档分析的多轮问答工作负载中,如图8所示,LMCache在TTFT(首字延迟)和ITL(Token间延迟)方面始终优于所有基线。在低QPS下,LMCache的TTFT减小了1.9至$8.1 \times$。在相同的TTFT下,LMCache在五种评估模型中实现了比最强基线高$2.3 – 14 \times$的吞吐量。ITL方面,LMCache比最佳基线减小了$7\%$至$92\%$。这得益于CPU内存能容纳更多缓存从而实现更高命中率,且LMCache块级别的传输比vLLM原生的逐页面传输更高效。

图8:与基础vLLM、基础vLLM CPU卸载以及两个商业替代方案相比,LMCache的TTFT减小了1.9–$8.1 \times$,并支持$2.3 – 14 \times$更高的推理吞吐量。
图8:与基础vLLM、基础vLLM CPU卸载以及两个商业替代方案相比,LMCache的TTFT减小了1.9–$8.1 \times$,并支持$2.3 – 14 \times$更高的推理吞吐量。

真实轨迹驱动的评估。使用来自F公司和G公司的真实输入输出Token分布轨迹进行评估。如图9和图10所示,在高QPS下,LMCache在五种模型中始终优于带有GPU前缀缓存的基础vLLM,将TTFT至少减小了$3.7 - 6.8 \times$,将ITL至少减小了19-$58\%$。

图9:基于F公司输入和输出分布的真实轨迹,比较LMCache和基础vLLM在三种不同模型上的表现。
图9:基于F公司输入和输出分布的真实轨迹,比较LMCache和基础vLLM在三种不同模型上的表现。
图10:上图和中图:基于F公司的轨迹比较LMCache和基础vLLM。下图:基于G公司的轨迹比较LMCache和基础vLLM。LMCache实现了更小的TTFT和ITL。
图10:上图和中图:基于F公司的轨迹比较LMCache和基础vLLM。下图:基于G公司的轨迹比较LMCache和基础vLLM。LMCache实现了更小的TTFT和ITL。

集中式存储服务器。使用带宽为15 Gbps的集中式远程服务器进行KV缓存共享。如图11所示,LMCache在不同QPS水平下始终优于所有基线,在相同TTFT下推理吞吐量提升了$1.3 – 3 \times$。

图11:与基础vLLM相比,具有远程后端卸载的LMCache在相同TTFT下推理吞吐量提升了1.3到$3 \times$。
图11:与基础vLLM相比,具有远程后端卸载的LMCache在相同TTFT下推理吞吐量提升了1.3到$3 \times$。

PD解耦。如图12所示,LMCache在尾部延迟方面显著优于vLLM的原生PD解耦。在平均TTFT方面,LMCache在四种模型中将平均TTFT减小了$1.53 - 1.84 \times$,将平均ITL减小了$1.12 - 1.66 \times$。这源于LMCache将KV缓存的块复制到GPU缓冲区并进行传输,而不是像vLLM那样在分散的分页内存中逐页传输。

图12:与vLLM的原生PD解耦相比,LMCache的PD解耦具有显著更低的尾部延迟,并实现了更低的平均TTFT和平均ITL。
图12:与vLLM的原生PD解耦相比,LMCache的PD解耦具有显著更低的尾部延迟,并实现了更低的平均TTFT和平均ITL。

组件级评估。图14显示了PD解耦中的延迟细分。LMCache采用了更高效的KV缓存传输机制,实现了更快的传输,从而减少了端到端延迟。如表5所示,对于CPU卸载,LMCache实现了400Gbps的带宽,而vLLM原生CPU卸载仅为88 Gbps,这是因为LMCache逐块传输数据,减少了每次内存复制的开销。图13展示了异步计算的好处,将端到端延迟降低了$1.46 \times$。

图13:通过请求异步化,LMCache将KV缓存加载与推理计算(预填充或解码)重叠。
图13:通过请求异步化,LMCache将KV缓存加载与推理计算(预填充或解码)重叠。
图14:与vLLM的原生PD解耦相比,LMCache实现了小得多的传输延迟,从而减少了端到端延迟。
图14:与vLLM的原生PD解耦相比,LMCache实现了小得多的传输延迟,从而减少了端到端延迟。
MethodAchieved Bandwidth
LMCache400Gbps
vLLM's Native CPU Off oading88 Gbps

表5:与vLLM原生的CPU卸载相比,LMCache在从CPU内存加载KV缓存时实现了高得多的加载带宽。

敏感性研究。图15显示了不同网络带宽和上下文长度下的预填充延迟。在低带宽(32 Gbps)下,仅当输入上下文长度超过256K Token时,LMCache的加载才优于朴素的预填充。而在64或128 Gbps下,LMCache的加载始终具有更低的延迟。

图15:在32Gbps带宽下,仅当输入长度超过256K Token时,LMCache的KV缓存卸载才优于基础vLLM的预填充。在64或128Gbps下,LMCache在所有输入长度上都优于预填充。
图15:在32Gbps带宽下,仅当输入长度超过256K Token时,LMCache的KV缓存卸载才优于基础vLLM的预填充。在64或128Gbps下,LMCache在所有输入长度上都优于预填充。

SGLang结果。图16报告了集成SGLang的结果。与未启用CPU卸载的SGLang相比,LMCache实现了更高的吞吐量和更低的延迟。与SGLang的原生CPU卸载相比,LMCache实现了相当的性能,并额外支持了跨分层存储设备的高效分布式存储后端。

图16:在Qwen3-32B模型上,LMCache的CPU卸载实现了与SGLang原生CPU卸载相当的性能。
图16:在Qwen3-32B模型上,LMCache的CPU卸载实现了与SGLang原生CPU卸载相当的性能。

补充细节

从远程存储加载快于预填充。传统上认为从远程存储加载数据比执行完整预填充要慢,这主要是由于Amazon S3等远程对象存储的历史吞吐量较低。然而,最近远程存储性能大幅提升(例如Amazon S3 Express吞吐量接近1 GBps)。用户采用LMCache从其远程对象存储加载KV缓存,与完整预填充相比,TTFT降低了$22 - 32\%$。这表明远程后端可以同时提高缓存命中率并降低TTFT。

上下文截断降低前缀缓存命中率。许多工业界用户采用滑动窗口机制处理受GPU内存限制的长上下文输入,即截断输入以仅保留最新的Token。然而,根据F公司的真实轨迹,这种方法使前缀缓存命中率从大约$85\%$大幅下降到$45\%$,因为截断的输入不再匹配先前缓存上下文的前缀。应避免动态添加或删除上下文Token,因为这会使前缀KV缓存重用失效。

偏好容器化代码。随着LLM推理规模的增长,大多数生产环境依赖Kubernetes管理GPU集群。因此,通过Docker镜像等容器化环境部署推理引擎和LMCache已成为行业标准实践。许多用户仅依赖官方Docker镜像,而不会深入修改LMCache的源代码。

生产系统中出乎意料的高命中率。客户在部署LMCache之前,并未预料到会有如此高的前缀缓存命中率(例如G公司在生产环境中达到了$50\%$的命中率)。以前人们认为KV缓存只能用于固定的系统提示,但现代应用越来越多地表现出“动态可重用的上下文”(如对话历史、RAG流水线),这显著提高了实际部署中的整体缓存命中率。

工业界与学术界用户的差异。工业界急需高效的KV缓存卸载解决方案,因此LMCache的重点转向了提高性能、稳定性和兼容性,而降低了为集成专门的注意力机制(如选择性Token丢弃)设计灵活API的优先级,这使得LMCache在学术界不太受欢迎。下一步,LMCache将设计更灵活的API以满足双方需求。

编程语言的灵活性与性能。尽管当前工业界的焦点逐渐从广泛的兼容性转向更高的效率(如用Rust或$C++$重写ML库),LMCache继续使用经过精心优化设计的Python。这种方法允许系统更快地演进,获得更多社区贡献,同时仍保持与替代方案相当的性能。

社区驱动的演进。LMCache迅速从研究原型演变为广泛采用的工业框架,关键原因在于社区贡献者的积极参与。如今,它已经支持跨四种处理器类型和两个推理引擎的8种以上存储后端(如NFS, S3, InfiniStore等),这些贡献均来自积极提交代码的行业合作伙伴。

结论

本文介绍了LMCache,这是首个开源且被最广泛采用的、用于企业级LLM推理的生产就绪KV缓存层。通过将KV缓存视为一等数据结构,LMCache将LLM引擎从孤立的Token处理器转变为计算和存储的分布式生态系统。评估表明,与开源基线和商业API相比,LMCache始终能提供显著的吞吐量提升和延迟降低。LMCache已在生产环境中迅速被采用,企业利用其能力在万亿Token规模的部署中保持低延迟并降低成本。

展望未来,LMCache指向了一个更广泛的转变:诸如KV缓存等AI原生数据将越来越成为扩展LLM推理和智能体工作负载的基础。通过将KV缓存确立为标准化的存储和通信媒介,LMCache为未来的系统奠定了基础,这些系统将不再把推理视为孤立的会话,而是视为持久的、感知缓存的计算结构。

参考文献引用汇总

在方法细节及实验分析中,本文引用了以下关键文献来支撑其设计与分析:
- 关于前缀缓存减少冗余计算降低TTFT的工作:引用了 Chen 等人 (2024, 2025) [4, 5]、Gao 等人 (2024) [9] 等多篇文献,指出前缀缓存能直接降低预填充延迟和GPU耗时。
- 关于现代高吞吐量推理引擎及其分页内存架构:引用了 vLLM (Kwon 等人, 2023) [18] 和 SGLang (Zheng 等人, 2024) [35],说明了分页注意力内存(16-64 KB页面)的广泛使用。
- 关于长上下文评估基准:引用了 LongBench (Bai 等人, 2024) [2] 以及 vLLM 官方基准测试脚本 (Kwon 等人, 2023) [18] 用于实验数据的生成与评估。
- 关于避免动态修改上下文Token以维持缓存命中率的工业界经验:引用了 Ji (2025) [14] 的研究,强调应避免截断输入,否则会使前缀KV缓存重用失效。