这篇文章的核心内容是介绍了一个名为MOONCAKE的系统,它是专门为服务大型语言模型(LLM)聊天机器人而设计的。MOONCAKE通过一种以KVCache(键值缓存)为中心的解耦架构,优化了LLM的推理服务,特别是在处理长上下文输入时表现优异。文章详细阐述了MOONCAKE的设计原理、实现方法以及实验评估,展示了其在提高吞吐量、降低延迟和优化资源利用方面的显著优势。

背景知识

  • LLM服务的挑战:随着LLM在各种场景中的广泛应用,服务工作负载变得多样化,对服务级别目标(SLO)的要求也日益严格。SLO通常涉及延迟相关的指标,如首次标记时间(TTFT)和标记之间的时间(TBT)。为了满足这些要求,需要高效利用GPU集群中的各种资源。
  • KVCache的重要性:KVCache是LLM推理过程中的关键中间数据,通过缓存和重用KVCache,可以显著减少计算量,从而提高推理效率。

研究方法

  • 解耦架构:MOONCAKE采用了解耦架构,将预填充(prefill)和解码(decoding)阶段分离,并利用GPU集群中的CPU、DRAM、SSD和RDMA资源构建了一个分布式KVCache(称为MOONCAKE Store)。这种架构允许在不同节点之间共享和传输KVCache,以实现更高效的缓存利用。
  • 全局调度器(Conductor):MOONCAKE的核心是一个全局调度器,负责根据当前KVCache的分布和工作负载特征来调度请求。调度器的目标是在满足SLO的前提下最大化吞吐量。
  • KVCache管理:MOONCAKE Store以分页块的形式管理KVCache,使用哈希键进行去重,并根据访问频率动态调整缓存块的副本数量,以减少热点缓存的访问延迟。
  • 传输引擎:为了高效地在节点之间传输KVCache,MOONCAKE设计了一个高性能的传输引擎,能够充分利用多个RDMA NIC设备,并通过拓扑感知路径选择和端点池化等技术提高传输效率和可靠性。

实验评估

  • 工作负载:实验使用了三种工作负载,包括来自实际应用的对话工作负载、工具&代理工作负载,以及合成工作负载,以涵盖不同的推理场景。
  • 性能指标:主要评估指标包括TTFT、TBT、有效请求容量(在满足SLO的情况下处理的请求数量)以及预填充阶段的GPU计算时间。
  • 结果
  • 有效请求容量:与基线系统vLLM相比,MOONCAKE在不同工作负载下显著提高了有效请求容量,最高可达498%。
  • 预填充GPU时间:MOONCAKE通过全局缓存显著减少了预填充阶段的GPU计算时间,与vLLM相比,分别减少了36%、53%和64%。
  • 缓存命中率:MOONCAKE Store的全局缓存设计显著提高了缓存命中率,与本地缓存相比,最大提高了136%,从而减少了预填充计算时间。
  • 传输性能:MOONCAKE的传输引擎在不同网络配置下均展现出较低的延迟和较高的带宽利用率,与TCP协议相比,传输速度分别快2.4倍和4.6倍。

关键结论

  • MOONCAKE通过其创新的以KVCache为中心的解耦架构,在满足严格SLO的同时,显著提高了LLM聊天机器人的吞吐量和资源利用效率。
  • 分布式KVCache的设计使得在不同节点之间共享和重用KVCache成为可能,这对于处理长上下文输入尤为重要。
  • 全局调度器和高效的传输引擎是实现MOONCAKE高性能的关键组件。
  • 实验结果表明,MOONCAKE在多种工作负载下均优于现有的LLM服务系统,证明了其在实际应用中的有效性和潜力。

这里是自己的论文阅读记录,感兴趣的话可以参考一下,如果需要阅读原文的话可以看这里,如下所示:

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_KVCache

官方项目地址在这里,如下所示:

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_Mooncake_02

摘要

MOONCAKE 是 Moonshot AI 开发的 LLM 聊天机器人服务 Kimi 的服务平台。该平台采用以 KVCache 为中心的解耦架构,不仅分离了预填充(prefill)和解码(decoding)集群,还高效利用了 GPU 集群中未充分利用的 CPU、DRAM、SSD 和 NIC 资源,构建了解耦的 KVCache。MOONCAKE 的核心是其以 KVCache 为中心的全局缓存和一个旨在最大化吞吐量同时严格遵守与延迟相关的服务级别目标(SLO)的调度器。我们的实验表明,MOONCAKE 在处理长上下文输入的场景中表现出色。在使用真实轨迹的测试中,与基线方法相比,MOONCAKE 将有效请求容量提高了 59% 至 498%,同时遵守 SLO。目前,MOONCAKE 已在数千个节点上运行,每天处理超过 1000 亿个标记。在实际部署中,MOONCAKE 的创新架构使 Kimi 在 NVIDIA A800 和 H800 集群上分别能够处理比以前的系统多 115% 和 107% 的请求。

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_KVCache_03

1. 引言

随着大型语言模型(LLMs)在各种场景中的快速采用,LLM 服务的工作负载变得极为多样化。这些工作负载在输入/输出长度、到达分布以及最重要的不同服务级别目标(SLOs)方面有所不同。作为模型即服务(MaaS)提供商,Kimi 的主要目标之一是解决一个具有多个复杂约束的优化问题。优化目标是最大化整体有效吞吐量,这直接影响收入,而约束则反映了不同级别的 SLOs。这些 SLOs 通常涉及满足延迟相关要求,主要是首次标记时间(TTFT)和标记之间的时间(TBT)。为了实现这一目标,一个先决条件是充分利用 GPU 集群中可用的各种资源。具体来说,尽管 GPU 服务器目前被提供为高度集成的节点(例如,DGX/HGX 超级计算机),但有必要将它们解耦并重构为几个解耦的资源池,每个资源池都针对不同但协作的目标进行优化。例如,许多其他研究人员建议将预填充服务器与解码服务器分开,因为这两个阶段的 LLM 服务具有非常不同的计算特性。进一步推进这种解耦策略,我们通过将 GPU 集群的 CPU、DRAM、SSD 和 RDMA 资源进行池化,构建了解耦的 KVCache,称为 MOONCAKE Store。这种新架构利用未充分利用的资源,实现了高效的近 GPU 前缀缓存,显著提高了全局缓存容量和节点间传输带宽。由此产生的分布式 KVCache 系统体现了“用更多存储换更少计算”的原则。因此,如图 1 所示,它显著提高了 Kimi 在满足许多重要现实场景所需 SLO 的最大吞吐量容量。在本文中,我们首先深入探讨这种策略对 LLM 服务的好处,并使用真实数据进行实证评估(第 2.2 节)。然后,我们将详细介绍实现这一 PB 级解耦缓存的设计选择,该缓存通过 8×400 Gbps 的 RDMA 网络进行互连(第 3.2 节)。基于这一想法,我们还发现 KVCache 的调度是 LLM 服务的核心,因此提出了相应的解耦架构。图 2 展示了我们的当前以 KVCache 为中心的解耦架构,用于 LLM 服务,称为 MOONCAKE。对于每个请求,全局调度器(Conductor)将选择一对预填充和解码实例,并按照以下步骤调度请求:1)将尽可能多的可重用 KVCache 转移到选定的预填充实例;2)以块/层的方式完成预填充阶段,并持续将输出 KVCache 流式传输到相应的解码实例;3)加载 KVCache 并将请求添加到解码实例的连续批处理过程中以生成请求输出。

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_KVCache_04

尽管这个过程看起来很直接,但选择策略是复杂的,因为存在许多限制。在预填充阶段,主要目标是尽可能多地重用 KVCache,以避免冗余计算。然而,分布式 KVCache 池在容量和访问延迟方面面临着挑战。因此,指挥官(Conductor)负责以 KVCache 意识的方式调度请求,并执行诸如交换和复制等调度操作。最热门的块应该被复制到多个节点上,以避免获取拥堵,而最冷的块应该被交换出去,以减少保留成本。相比之下,解码阶段有不同的优化目标和约束。目标是在解码批次中聚合尽可能多的标记,以提高模型的 FLOPs 利用率(MFU)。然而,这个目标不仅受到 TBT SLO 的限制,还受到可以包含在 VRAM 中的聚合 KVCache 的总大小的限制。

在第 4 节中,我们将详细介绍我们的以 KVCache 为中心的请求调度算法,该算法在平衡实例负载和用户体验(以 TTFT 和 TBT SLO 衡量)方面取得了平衡。这包括一个基于启发式的自动热点迁移方案,该方案在不需要精确预测未来 KVCache 使用情况的情况下复制热点 KVCache 块。实验结果表明,我们的以 KVCache 为中心的调度可以在现实场景中显著降低 TTFT。我们还将描述在实现过程中所做的主要设计选择,特别是那些当前研究中未涵盖的内容。例如,关于 P/D 解耦,目前由于带宽要求和与分块预填充(例如,Sarathi-Serve)相关的权衡,其在大规模实践中的可行性存在争议。我们通过与 vLLM 的比较表明,通过高度优化的传输引擎,可以管理通信挑战,并且在具有严格 SLO 限制的场景中,P/D 解耦是更好的选择(第 5.2 节)。此外,我们讨论了如何实现一个单独的预填充节点池,以无缝处理上下文长度的动态分布。我们采用分块流水线并行(CPP)机制来扩展单个请求在多个节点上的处理,这对于减少长上下文输入的 TTFT 是必要的。与基于传统序列并行(SP)的解决方案相比,CPP 减少了网络消耗,并简化了对频繁弹性扩展的依赖(第 3.3 节)。目前,MOONCAKE 是 Kimi 的服务平台,并已成功处理了指数级的工作负载增长(每天超过 1000 亿个标记)。根据我们的历史统计数据,MOONCAKE 的创新架构使 Kimi 在 A800 和 H800 集群上分别能够处理比以前的系统多 115% 和 107% 的请求。为了确保我们的结果具有可重复性,同时保护专有信息,我们还提供了使用基于 LLaMA3-70B 架构的虚拟模型的详细实验结果,这些结果是根据实际工作负载的重放轨迹得出的。这些轨迹以及 MOONCAKE 的 KVCache 传输基础设施已在 GitHub - kvcache-ai/Mooncake: Mooncake is the serving platform for Kimi, a leading LLM service provided by Moonshot AI. 开源。在使用公共数据集和实际工作负载的端到端实验中,MOONCAKE 在长上下文场景中表现出色。与基线方法相比,MOONCAKE 可以在满足 SLO 的情况下将有效请求容量提高多达 498%。在第 5.3 节中,我们将 MOONCAKE Store 与本地缓存设计进行了比较,发现 MOONCAKE Store 的全局缓存设计显著提高了缓存命中率。在我们的实验中,缓存命中率比本地缓存高出多达 2.36 倍,从而节省了多达 48% 的预填充计算时间。据我们所知,MOONCAKE 是第一个在大规模部署场景中证明使用分布式 KVCache 池在不同聊天会话和查询之间共享 KVCache 的显著好处的系统。我们还评估了支持 MOONCAKE 中高速 RDMA 传输的传输引擎的性能,结果表明它比现有解决方案分别快约 2.4 倍和 4.6 倍(第 5.4 节)。

2. 前提和问题定义

2.1 LLM 服务的服务级别目标

现代大型语言模型(LLMs)基于 Transformer 架构,该架构利用注意力机制和多层感知器(MLP)来处理输入。流行的基于 Transformer 的模型,如 GPT 和 LLaMA,采用仅解码器结构。每个推理请求在逻辑上分为两个阶段:预填充阶段和解码阶段。在预填充阶段,所有输入标记并行处理,因此它通常是计算密集型的。这个阶段生成第一个输出标记,同时存储计算出的键和值的中间结果,称为 KVCache。然后,解码阶段使用这个 KVCache 自回归地生成新标记。由于自回归生成的限制,它每次批处理只处理一个标记,这使得它受到内存限制,并且计算时间随着批大小的增加而亚线性增加。因此,在解码阶段广泛使用的一种优化是连续批处理。在每次迭代之前,调度器检查状态,并将新到达的请求添加到批次中,同时移除已完成的请求。由于预填充和解码阶段具有不同的特性,MaaS 提供商设置了不同的指标来衡量它们对应的服务级别目标(SLOs)。具体来说,预填充阶段主要关注从请求到达时间到第一个标记生成时间之间的延迟,称为首次标记时间(TTFT)。另一方面,解码阶段关注相同请求的连续标记生成之间的延迟,称为标记之间的时间(TBT)。在实际部署中,如果监控器检测到未满足 SLOs,我们需要么增加推理资源,要么拒绝一些传入的请求。然而,由于当前 GPU 的供应有限,弹性扩展推理集群通常是不可行的。因此,我们主动拒绝那些被预测为无法满足 SLOs 的请求,以减轻集群的负载。我们的主要目标是在遵守 SLOs 的情况下最大化整体吞吐量,这一概念在其他研究中被称为有效吞吐量(goodput)。

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_KVCache_05

2.2 用更多存储换更少计算

为了满足上述严格的 SLOs,一个常见的解决方案是缓存之前生成的 KVCache,并在找到前缀匹配时重用它。然而,现有方法通常将缓存限制在本地 HBM 和 DRAM 中,假设全局调度所需的传输带宽会过高。但我们将在第 5.3 节中描述,本地 DRAM 的容量仅支持高达 50% 的理论缓存命中率,因此设计全局缓存是必要的。在本节中,我们基于表 1 中描述的模型符号进行数学分析,并结合 LLaMA3-70B 的特定参数。本质上,当前流行的 LLMs 是自回归语言模型,其中每个标记的 KVCache 只依赖于它自己和前面的标记。因此,对应于相同输入前缀的 KVCache 可以被重用,而不会影响输出精度。如果当前请求的提示长度为 n,与之前缓存的 KVCache 共享长度为 p 的公共前缀,其预填充过程可以优化如下:

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_KVCache 为中心的架构_06

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_KVCache_07

在这种情况下,重用 KVCache 不仅减少了 GPU 时间和成本,还通过改善 TTFT 提升了用户体验。当模型尺寸较大时,满足带宽 B 相对于计算吞吐量 G 的标准更容易。例如,当在配备 8×A800 的机器上运行 LLaMA3-70B 并假设前缀长度为 8192 时,方程 2 得出的最小所需 B 为 6 GB/s。对于 8×H800 机器,B 的要求将扩大到 19 GB/s。此外,在实际场景中,由于传输阶段不能完美重叠,实际带宽要求甚至更高。然而,正如我们将在第 5.4.2 节中展示的那样,每台 NVIDIA A800 HGX 网络的 100 Gbps NIC 足以满足这些标准。

3. MOONCAKE 的设计

3.1 概述

如图 2 所示,MOONCAKE 采用了解耦架构,不仅将预填充节点与解码节点分开,还将 GPU 集群的 CPU、DRAM、SSD 和 RDMA 资源进行分组,以实现解耦的 KVCache。为了调度所有这些解耦的组件,MOONCAKE 在其中心实现了一个名为指挥官(Conductor)的全局调度器。指挥官负责根据当前 KVCache 的分布和工作负载特征分发请求。MOONCAKE Store(第 3.2 节详细描述)管理这些 KVCache 块的存储和传输。具体来说,图 3 展示了一个请求的典型工作流程。一旦完成标记化,指挥官就会选择一对预填充节点和一个解码节点,并启动一个包含四个步骤的工作流程:1)KVCache 重用:选定的预填充节点(组)接收一个包含原始输入、可以重用的前缀缓存块键以及分配给请求的完整缓存块键的请求。它根据前缀缓存块键从远程 CPU 内存中将前缀缓存加载到 GPU 内存中,以引导请求。如果没有前缀缓存,则跳过此步骤。此选择平衡了三个目标:尽可能多地重用 KVCache、平衡不同预填充节点的工作负载以及保证 TTFT SLO。这导致了以 KVCache 为中心的调度,我们将在第 4 节中进一步讨论。2)增量预填充:预填充节点使用前缀缓存完成预填充阶段,并将新生成的增量 KVCache 存储回 CPU 内存。如果未缓存的输入标记数量超过某个阈值,预填充阶段将被分成多个块,并以流水线方式执行。此阈值被选为充分利用相应 GPU 的计算能力,并且通常大于 1000 个标记。使用分块但仍然解耦的预填充节点的原因在第 3.3 节中进行了说明。3)KVCache 传输:MOONCAKE Store 部署在每个节点上,以管理和传输这些缓存。此步骤异步执行并与上述增量预填充步骤重叠,将每个模型层生成的 KVCache 流式传输到目标解码节点的 CPU 内存中,以减少等待时间。4)解码:在解码节点的 CPU 内存中收到所有 KVCache 后,请求加入下一批次,以连续批处理方式进行。解码节点由指挥官根据其当前负载预先选择,以确保不会违反 TBT SLO。

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_KVCache 为中心的架构_08

3.2 MOONCAKE Store:KVCache 的缓存

MOONCAKE 的核心是其分布式全局 KVCache 缓存的高效实现,称为 MOONCAKE Store。如第 2.2 节所述,重用缓存的 KVCache 不仅可以减少计算成本,还可以通过减少 TTFT 来改善用户体验,特别是当聚合带宽得到充分利用时。然而,实现完全利用是具有挑战性的,因为带宽可以达到高达 8×400 Gbps,与 DRAM 带宽相当。我们首先介绍 MOONCAKE Store 如何管理 KVCache(第 3.2.1 节),包括其存储方案和逐出策略。在第 3.2.2 节中,我们描述了 MOONCAKE Store 的基于对象的 API 和内存传输 API。在第 3.2.3 节中,我们将详细介绍 MOONCAKE Store 的传输引擎的设计,这是一个高性能的零拷贝 KVCache 传输系统,旨在最大化使用每台机器上的多个 RDMA NIC。它通过诸如拓扑感知路径选择和端点池化等技术提高了执行效率和可靠性。

3.2.1 KVCache 管理

在 MOONCAKE Store 中,所有 KVCache 都作为分页块存储在分布式缓存池中。块大小,即每个块中包含的标记数量,由模型大小和最佳网络传输大小决定,通常范围从 16 到 512 个标记。每个块都附加有一个由其自身的哈希和其前缀确定的哈希键,用于去重。相同的哈希键可能在不同节点上有多个副本,以减少热点缓存访问延迟,由我们在第 4.2 节中描述的缓存负载平衡策略控制。MOONCAKE Store 为每个缓存块在缓存池中分配空间,并记录诸如块键及其地址等元数据。当缓存池满了时,MOONCAKE Store 采用最近最少使用(LRU)策略来逐出一个现有的缓存块——除非该块当前正被一个正在进行的请求访问——并用新块覆盖被逐出块的空间。

3.2.2 接口

在更高层次上,MOONCAKE Store 提供了基于对象的 API,如 put、get 和 change_replica。这些便于以解耦的方式缓存 KVCache,将 KVCache 的小块组织为内存对象,并允许指挥官调整每个 KVCache 块的副本数量,以实现更高的带宽聚合。这些功能由一组同步批量传输 API 支持,详细信息见清单 1。传输操作适用于 DRAM 和 GPU VRAM,并将在最优情况下使用 GPU Direct RDMA,前提是已预先注册了指定的内存区域。可以通过 getTransferStatusAPI 异步监控这些操作的完成情况,该 API 报告传输是否正在进行或是否遇到错误。

清单 1:MOONCAKE Store 中的内存传输 API

int registerLocalMemory(void *vaddr, size_t len, const string &type);
BatchID allocateBatchID(size_t batch_size);
int submitTransfer(BatchID batch_id, const vector<Request> &entries);
int getTransferStatus(BatchID batch_id, int request_index, Status &status);
int freeBatchID(BatchID batch_id);

3.2.3 传输引擎

为了有效地实现上述 API,设计了一个传输引擎以实现几个关键目标:1)有效地将传输任务分配到多个 RDMA NIC 设备上;2)从 API 中抽象出 RDMA 连接管理的复杂性;3)适当地处理临时网络故障。这个传输引擎经过精心设计,以满足每个目标。

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_Mooncake_09

网络设置 MOONCAKE 的好处依赖于高带宽网络互连。目前,我们使用标准的 HGX 机器,其中每个 A800 GPU 都配有一个 100/200 Gbps NIC,每个 H800 GPU 都配有一个 200/400 Gbps NIC,这与内存带宽相当,现有的库(除了 NCCL)未能充分利用这种容量。至于 NCCL,它不能优雅地处理由于添加或移除节点/NIC 而导致的动态拓扑变化,并且不支持 DRAM 到 DRAM 的路径。相比之下,传输引擎会尝试在失败时寻找替代路径。为了缓解拥塞,网络使用了由云提供商调整的 RoCEv2。在调度器中,我们通过增加热点 KVCache 的副本数量(第 4.2 节)来缓解拥塞。

拓扑感知路径选择 现代推理服务器通常由多个 CPU 插槽、DRAM、GPU 和 RDMA NIC 设备组成。虽然从技术上讲,可以使用任何 RDMA NIC 从本地 DRAM 或 VRAM 向远程位置传输数据,但这些传输可能会受到 Ultra Path Interconnect (UPI) 或 PCIe Switch 带宽限制的限制。为了克服这些限制,MOONCAKE Store 实现了一种拓扑感知路径选择算法。在处理请求之前,每个服务器都会生成一个拓扑矩阵,并将其广播到整个集群中。该矩阵将网络接口卡(NIC)分类为“首选”和“次要”列表,这些列表在内存注册期间指定。在正常情况下,从首选列表中选择一个 NIC 进行传输,以便在本地 NUMA 或通过本地 PCIe switch 进行 GPU Direct RDMA 的 RDMA 操作。在出现故障的情况下,可能会使用两个列表中的 NIC。该过程涉及根据内存地址识别适当的本地和目标 NIC,建立连接,并执行数据传输。例如,如图 4 所示,为了将本地节点中的缓冲区 0(分配给 cpu:0)中的数据传输到目标节点中的缓冲区 1(分配给 cpu:1),引擎首先根据本地服务器的拓扑矩阵识别 cpu:0 的首选 NIC,并选择其中一个,例如 mlx5_1,作为本地 NIC。同样,根据目标内存地址选择目标 NIC,例如 mlx5_3。这使得能够建立从 mlx5_1@local 到 mlx5_3@target 的 RDMA 连接,以执行 RDMA 读写操作。为了进一步最大化带宽利用率,单个请求的传输在 16 KB 的粒度上被内部划分为多个切片。每个切片可能使用不同的路径,使所有 RDMA NIC 协同工作。

端点管理 MOONCAKE Store 使用一对端点来表示本地 RDMA NIC 和远程 RDMA NIC 之间的连接。在实践中,每个端点包括一个或多个 RDMA 队列对对象。在 MOONCAKE Store 中,连接是按需建立的;端点在第一个请求之前保持未配对。为了防止大量端点减慢请求处理速度,MOONCAKE Store 使用端点池化,限制活动连接的最大数量。我们使用 SIEVE 算法来管理端点逐出。如果由于链路错误导致连接失败,它将从两侧的端点池中移除,并在下一次数据传输尝试期间重新建立。

故障处理 在多 NIC 环境中,一个常见的故障场景是特定 NIC 的临时不可用性,而其他路径可能仍然可以连接两个节点。MOONCAKE Store 被设计为能够有效地管理这种临时故障。如果识别到连接不可用,MOONCAKE Store 会自动识别一个替代的可达路径,并将请求重新提交到不同的 RDMA NIC 设备。此外,MOONCAKE Store 还能够检测到其他 RDMA 资源(包括 RDMA 上下文和完成队列)的问题。它会暂时避免使用这些资源,直到问题(例如链路故障)得到解决。

3.3 MOONCAKE 的预填充池

与不可侵犯的解码节点不同,设计一个单独且弹性的预填充池的必要性和最佳实践仍存在争议。例如,尽管许多研究人员共享我们的直觉,即使用解耦架构,但值得讨论的是,在引入分块预填充后,这种分离是否仍然必要。然而,在仔细考虑后,我们决定保持 MOONCAKE 的解耦架构。这一决定主要基于在线服务通常具有更严格的 SLOs 这一事实。虽然分块预填充减少了对解码的干扰,但在预填充阶段同时最大化 MFU 以及在解码阶段满足 TBT SLO 仍然具有挑战性。我们将在第 5.2 节的端到端实验中展示这一点。另一个重要原因是,我们认为预填充节点需要不同的跨节点并行设置,以处理长上下文,因为最近 LLMs 的可用上下文长度正在迅速增加,从 8k 增加到 128k,甚至高达 100 万个标记。通常,对于这种长上下文请求,输入标记的数量可能是输出标记的 10 到 100 倍,这使得优化 TTFT 至关重要。由于长上下文预填充中存在丰富的并行性,使用超过单个 8×GPU 节点来并行处理它们是可取的。然而,将张量并行(TP)扩展到多个节点需要每层进行两次基于 RDMA 的全归约操作,这会显著降低预填充节点的 MFU。最近,许多工作提出了序列并行(SP)。SP 将请求的输入序列分区到不同节点上以实现加速,即使长请求也能满足 TTFT SLO。然而,当应用于较短的输入请求时,与仅使用单节点 TP 相比,SP 的 MFU 较低。最近的研究提出了弹性序列并行,以动态扩展 SP 组。尽管这是可能的,但它增加了我们架构的复杂性。此外,SP 仍然需要频繁的跨节点通信,这会降低 MFU 并与节点间传输 KVCache 的网络资源竞争。为了解决这一问题,MOONCAKE 利用了仅解码器 Transformer 的自回归特性,并为长上下文预填充实现了分块流水线并行(CPP)。我们将预填充集群中的每 X 个节点分组成一个流水线预填充节点组。对于每个请求,其输入标记被分成块,每块的长度不超过预填充块大小。同一请求的不同块可以同时由不同节点处理,从而实现并行处理并减少 TTFT。CPP 提供了两个主要好处:1)类似于训练中的流水线并行,它只需要在每个流水线阶段的边界处进行跨节点通信,这可以轻松与计算重叠。这导致了更好的 MFU 和较少的网络资源与 KVCache 传输的争用。2)它自然适合短上下文和长上下文,对于短上下文预填充没有显著的开销,并且避免了频繁动态调整节点分区。这种基于流水线的加速方法在训练系统中已经进行了探索,但据我们所知,这是首次应用于推理阶段,因为长上下文推理只是最近才出现的。

4. 调度

4.1 预填充全局调度

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_KVCache 为中心的架构_10

以往关于 LLM 服务的研究通常采用基于负载均衡的策略,根据每个实例上分配的请求数量来评估负载。然而,在 MOONCAKE 中,预填充实例的选择考虑了额外的因素——不仅仅是负载,还有前缀缓存命中长度和可重用 KVCache 块的分布。虽然倾向于将请求路由到具有较长前缀缓存长度的预填充实例以减少计算成本,但由于高实例负载,可能需要将它们调度到其他节点以确保整体系统平衡并满足 TTFT SLOs。为了解决这些复杂性,我们提出了一个以缓存为中心的全局调度算法,考虑了由于前缀缓存而导致的预填充时间以及本地排队时间。算法 1 详细描述了我们的以 KVCache 为中心的预填充调度机制。对于每个新请求,块键将逐一与每个预填充实例的缓存键进行比较,以确定前缀匹配长度(prefix_len)。有了这些匹配信息,指挥官将根据请求长度和 prefix_len(因实例而异)估计相应的执行时间,使用一个多项式回归模型,该模型是根据离线数据拟合的。然后,它将该请求的估计等待时间加到该实例上的 TTFT 上。最后,指挥官将请求分配给 TTFT 最短的实例,并相应地更新该实例的缓存和排队时间。如果无法实现 SLO,指挥官将直接向上层返回 HTTP 429 Too Many Requests 响应状态码。该调度框架的骨干是直接的,但各种组件的工程实现的复杂性隐藏其中。例如,为了预测预填充阶段的计算时间,我们使用了一个基于离线测试数据得出的预测模型。该模型根据请求的长度和前缀缓存命中长度估计预填充持续时间。由于 Transformer 的计算模式规律,只要有足够的离线数据,这个预测的误差范围就很小。通过将所有排队请求的预填充时间相加来计算请求的排队时间。在实际实现中,TTFT 是并行计算的,与推理时间相比,处理时间可以忽略不计。预测传输时间的困难更大,因为它不仅取决于传输数据的大小,还取决于当前网络状态,特别是发送节点是否处于拥塞状态。这也需要热点 KVCache 块的复制,这将在第 4.2 节中讨论。

4.2 缓存负载平衡

在 MOONCAKE 中,每个预填充实例都有自己的本地前缀缓存集合。这些缓存的使用频率差异很大。例如,系统提示几乎被每个请求访问,而存储来自本地长文档内容的缓存可能只被一个用户使用。如第 4.1 节所述,指挥官在实现缓存匹配和实例负载之间的最佳平衡方面起着关键作用。因此,从分布式缓存系统的角度来看,负载平衡也起着重要作用。具体来说,它涉及如何备份缓存,以确保全局预填充调度能够实现高缓存命中率和低负载。一个简单的解决方案是收集每个块的全局使用情况,使用预测模型预测它们的未来使用情况,并据此做出调度决策。然而,与预填充时间的估计不同,工作负载高度动态,随时间显著变化。特别是对于一个经历用户基数快速增长的 MaaS 提供商来说,不可能准确预测未来的使用情况。因此,我们提出了一个基于启发式的自动热点迁移方案,以增强缓存负载平衡。如前所述,由于高实例负载,请求可能不会总是被定向到具有最长前缀缓存长度的预填充实例。在这种情况下,指挥官会将缓存的位置和请求转发到替代实例,如果估计的额外预填充时间比传输时间短。这个实例会主动从持有者那里检索 KVCache 并将其存储在本地。更重要的是,如果最佳远程前缀匹配长度不大于当前本地可重用前缀长度乘以一个阈值,我们更愿意计算输入标记。这两种策略不仅减少了请求的预填充时间,还促进了热点缓存的自动复制,使其能够在多个实例之间更广泛地分布。

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_KVCache_11

为了验证我们策略的有效性,我们进行了一个调度实验,将随机调度和负载均衡调度与我们的策略进行比较。我们还比较了第 4.1 节中描述的本地缓存感知调度和本节中描述的全局缓存感知调度,后者考虑了缓存负载平衡。在随机调度中,每个请求任意选择一个预填充实例。在负载均衡调度中,选择负载最轻的实例。具体来说,我们在 MOONCAKE 集群中构建了 16 个 8×A800 节点,并重放了第 5.2.1 节中描述的对话跟踪以进行实验。我们根据 TTFT 来评估每种调度算法的性能。实验结果如图 5 所示,表明我们的以 KVCache 为中心的调度算法优于随机和负载均衡调度。通过纳入缓存负载平衡,与本地缓存感知算法相比,全局缓存感知算法将平均 TTFT 进一步降低了 14%。

5. 评估

如前所述,根据 Kimi 的历史统计数据,与我们基于 vLLM 的以前系统相比,MOONCAKE 使 Kimi 能够在 A800 和 H800 集群上分别处理多 115% 和 107% 的请求。为了进一步验证这一结果并确保可重复性,在本节中,我们在 MOONCAKE 上进行了一系列端到端和消融实验,使用了一个虚拟的 LLaMA3-70B 模型,以解决以下问题:1)MOONCAKE 是否在现实场景中优于现有的 LLM 推理系统?2)与传统的前缀缓存方法相比,MOONCAKE Store 的设计是否显著提高了 MOONCAKE 的性能?

5.1 设置

测试平台。在重现实验期间,系统被部署在一个高性能计算节点集群上,以评估其性能。集群中的每个节点都配备了八个 NVIDIA-A800-SXM4-80GB GPU 和四个 200 Gbps RDMA NIC。MOONCAKE Store 中的 KVCache 块大小设置为 256。对于 MOONCAKE 的部署,每个节点根据启动参数作为预填充实例或解码实例运行。对于其他系统的部署,每个节点托管一个实例。指标。具体来说,我们测量每个请求的 TTFT 和 TBT,其中 TBT 计算为最长 10% 的标记到达间隔的平均值。如第 2 节所述,TTFT 的阈值设置为 30 秒,TBT 阈值根据场景分别设置为 100 毫秒、200 毫秒和 300 毫秒。我们将同时满足 TTFT 和 TBT 阈值的请求视为有效请求,所有请求中有效请求的比例为有效请求容量。为了简洁起见,后续未提及 TTFT 的实验假设满足 TTFT 阈值。为了更细致地比较缓存性能,我们还测量了预填充阶段的 GPU 时间和每个请求的缓存命中率。基线。我们使用 vLLM 作为实验基线,这是最先进的开源 LLM 服务系统之一。vLLM 特点是连续批处理和分页注意力技术,显著提高了推理吞吐量。尽管它具有优势,但 vLLM 的架构将预填充和解码阶段耦合在一起,这可能会干扰解码,特别是在涉及长上下文的场景中。vLLM 的最新更新整合了前缀缓存和分块预填充等特性,以改善长上下文场景中的性能指标,如 TTFT 和 TBT。在我们的实验中,我们还将这些 vLLM 特性进行了比较。在我们的实验中,我们使用了 vLLM 的最新版本(v0.5.1)。由于当前实现的限制,我们分别测试了该版本的前缀缓存和分块预填充特性。

5.2 端到端性能

在我们的端到端实验中,我们在各种工作负载下评估了 MOONCAKE 和基线系统处理请求的能力。具体来说,我们测量了在定义的 SLO 阈值内保持的最大吞吐量。我们在测试中使用了三种类型的工作负载:两个来自 Kimi 的真实世界跟踪,分别代表在线对话和工具&代理交互,以及一个合成工作负载,以涵盖不同的推理场景。我们将首先描述这些工作负载的独特特征,然后讨论结果。最后,我们分析了预填充阶段的 GPU 计算时间,进一步证明了 MOONCAKE Store 在提高缓存利用率和降低计算成本方面的优势。

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_KVCache_12

5.2.1 工作负载

对话工作负载。聊天机器人是 LLM 最常见的应用之一,使对话请求成为 LLM 推理的极具代表性的工作负载。如表 2 所示,对话工作负载包含大量长上下文请求,长度可达 128k 标记,平均约为 12k 标记,与当前长上下文数据集中的数据长度相当。此外,由于多轮对话,该工作负载的平均前缀缓存比例约为 40%。我们从在线推理集群中采样了 1 小时的对话跟踪,每条记录包括输入和输出长度以及到达时间戳。根据这些时间戳分发请求,并在模型输出达到预定长度时提前终止。

工具&代理工作负载。最近的研究涉及将 LLM 部署为工具或代理以执行任务,这些任务通常包含预先设计的、往往较长的系统提示,这些提示是完全重复的。我们收集了工具&代理工作负载的跟踪,同样是在 1 小时内采样。如表 2 所示,该工作负载具有较短的输入和输出长度,但前缀缓存比例很高。

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_架构_13

合成工作负载。合成工作负载是基于公开可用数据集组合构建的。我们将真实跟踪中的请求分为三类:短对话、工具和代理调用以及长文本摘要和问答。对于每一类,我们选择了以下数据集:ShareGPT、Leval 和 LooGLE。ShareGPT 包含多轮对话,输入长度较短。Leval 用于评估模型在长上下文上的性能,模拟工具和代理交互中常见的长系统提示场景。LooGLE 专为长上下文问答和摘要任务设计,输入长度可达 100k 标记,包括多轮问答和单轮摘要,非常适合长文本摘要和问答场景。总体而言,合成工作负载具有最长的平均输入长度。尽管其前缀缓存比例最高,但缓存命中较为分散,因此需要较大的缓存容量。在预处理过程中,将每轮对话映射为一个单独的请求,包括之前互动的输入和输出。对于具有相同长提示的多个问题的数据集,将每个问题及其前面的提示视为一个单独的请求。我们将处理过的数据集按 1:1:1 的比例组合,保留多轮对话请求的顺序关系,同时随机打乱它们。由于数据集未指定到达时间,我们通过泊松过程以定义的速率分发请求,以模拟现实条件。

5.2.2 有效请求容量

为了评估在不同工作负载下能够满足 SLO 的最大请求数量,我们测试了四种系统配置:MOONCAKE、vLLM、具有前缀缓存特性的 vLLM 和具有分块预填充特性的 vLLM,每种配置都使用 16 个节点。对话工作负载。该工作负载的结果如图 1 所示。该工作负载以变化的输入长度和较长的输出长度为特征,导致 vLLM 系统在预填充阶段因长上下文而出现显著的 TBT 波动。尽管分块预填充减少了对解码的干扰,但在预填充阶段增强 MFU 与解码阶段的 TBT 约束之间保持平衡仍然具有挑战性。尽管满足了 TTFT SLO,但其有效请求容量仍然次优。与 vLLM 相比,MOONCAKE 在有效请求容量方面实现了显著增长。

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_Mooncake_14

工具&代理工作负载。相比之下,工具&代理工作负载具有较高的前缀缓存比例和较短的输出长度,这使得 vLLM 系统在预填充时间对输出的影响最小。然而,如图 6 所示,vLLM 和具有分块预填充的 vLLM 在解码过程中受到更严重的干扰,因为预填充处理时间较长,导致其有效缓存容量低于具有前缀缓存的 vLLM。MOONCAKE 使用全局缓存池显著增加了缓存容量,并通过节点间传输优化缓存利用率,在高前缀缓存场景中表现出色。因此,与具有前缀缓存的 vLLM 相比,在 200 毫秒阈值下,MOONCAKE 将有效缓存容量提高了 42%。

合成工作负载。合成工作负载具有最长的平均输入长度和分散的缓存热点,这导致在较小的缓存容量下缓存利用率较差。如图 7 所示,大多数由 MOONCAKE 处理的请求在 100 毫秒内保持 TBT,而 vLLM 处理的约 20% 的请求超过了 300 毫秒。具有前缀缓存和分块预填充的系统的性能与 vLLM 类似,因为它们未能减轻长上下文对解码阶段的影响。与 vLLM 相比,MOONCAKE 在 200 毫秒阈值下将有效请求容量提高了 40%。

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_架构_15

5.2.3 预填充 GPU 时间

预填充 GPU 时间与请求的 TTFT 和服务成本呈正相关,由请求的输入长度和缓存命中率决定。我们在图 8 中分析了不同工作负载下预填充阶段的平均 GPU 时间。对于 MOONCAKE,由于输入长度较长且前缀缓存比例较低,对话工作负载的预填充 GPU 时间最长。具有最高前缀缓存比例和分散缓存热点的合成工作负载在 MOONCAKE 的全局缓存池中实现了最佳缓存命中率。因此,尽管其平均输入长度最长,但其预填充 GPU 时间比对话工作负载少。最后,由于平均输入长度最短且前缀缓存比例相对较高,工具&代理工作负载的预填充 GPU 时间最短。在不同系统之间,MOONCAKE 通过充分利用全局缓存进行前缀缓存,显著减少了 GPU 时间,与 vLLM 相比,分别减少了对话、工具&代理和合成工作负载的 GPU 时间 36%、53% 和 64%。具有前缀缓存的 vLLM 使用存储在 HBM 上的本地缓存,其缓存容量远低于 MOONCAKE。其预填充 GPU 时间分别是 MOONCAKE 的 1.43 倍和 1.40 倍,用于对话和工具&代理工作负载。然而,在合成工作负载中,由于缓存热点更加分散,具有前缀缓存的 vLLM 的预填充 GPU 时间几乎与 vLLM 相同,是 MOONCAKE 的 2.59 倍。具有分块预填充的 vLLM 牺牲了一些预填充效率,以在解码阶段保持较低的 TBT,导致最长的预填充 GPU 时间,分别是三种工作负载的 1.90 倍、2.68 倍和 3.33 倍。

5.3 MOONCAKE Store

为了解答问题 2,我们考察了 MOONCAKE Store 的全局缓存池对系统性能的影响。我们的分析表明,尽管使用本地 DRAM 构建 KVCache 内存比仅使用 HBM 增加了缓存容量,但将缓存限制在单个节点上仍然导致次优的缓存利用率。我们首先进行缓存容量需求的定量分析,然后通过实际工作负载实验展示其优势。

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_架构_16

5.3.1 缓存容量需求的定量分析

以 LLaMA3-70B 模型为例,单个标记的 KVCache 所需大小为 320 KB。尽管有可能预留大约 1 TB 的 DRAM 用于本地缓存,但这种设置仅能存储约 300 万个标记,这显然不足。图 9 显示了在各种工作负载及其组合下,理论上的前缀缓存命中率与不同缓存容量的关系。结果表明,在大多数场景中,本地缓存容量为 300 万个标记时,无法达到理论最大命中率的 50%。我们还确定,在这些工作负载中,当缓存容量达到 5000 万个标记时,几乎达到了理论最大命中率的 100%,这需要至少将 20 个节点的 DRAM 进行池化。这些结果表明,与本地缓存相比,全局缓存显著提高了容量,从而提高了缓存命中率并减少了 GPU 时间。

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_架构_17

5.3.2 实际工作负载实验

为了评估全局缓存与本地缓存机制的有效性,我们关注两个指标:缓存命中率和预填充阶段的平均 GPU 计算时间。我们配置了一个包含 10 个预填充节点的集群,并将所有请求的输出限制为 1,以隔离解码阶段的影响。在本地缓存设置中,每个节点拥有 300 万个标记的容量,但只能访问自己的缓存。全局调度器被编程为将请求导向具有更高前缀匹配比率的节点,以最大化缓存利用率。相比之下,在全局缓存设置中,每个节点同样拥有 300 万个标记的容量,但可以在所有节点之间共享缓存,得到主动的节点间缓存迁移的支持。实验数据如图 10 所示,表明全局缓存实现了更高的缓存命中率和更短的平均预填充 GPU 计算时间,涵盖了所有测试工作负载。与本地缓存相比,全局缓存的最大缓存命中率增加了 136%,预填充计算时间减少了多达 48%。

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_KVCache 为中心的架构_18

5.3.3 缓存副本

基于第 4.2 节中讨论的缓存负载平衡调度策略,MOONCAKE Store 中的缓存键可能在不同机器上有副本,从而减少对热点缓存的访问延迟。为了进一步研究系统的动态行为,我们统计了三个工作负载中各缓存键的副本数量,如图 11 所示。可以看到,在对话和工具&代理工作负载中,存在高度集中的热点缓存(例如,排名前 100 的键),在系统稳定后,这些热点缓存的副本几乎出现在预填充池中的每个实例上。相比之下,合成工作负载的共享前缀缓存较少,导致副本数量较少,即使是排名前 10 的块也可能出现波动。这表明我们的调度策略在第 4.2 节中有效地为热点缓存提供了副本,特别是在前缀缓存高度集中的场景中。

5.4 KVCache 传输性能

5.4.1 传输引擎

MOONCAKE 的传输引擎旨在促进节点之间的高效缓存传输。我们将它的延迟与两种流行的方案进行比较,考虑了两个替代基线:使用 Gloo 后端的 torch.distributed 和基于 TCP 的传输。所有方案都以 64 的并发级别进行测试,最小传输粒度为 128 KB。如图 12 所示,传输引擎的延迟始终显著低于其他方法。在传输 40 GB 数据(对应于 LLaMA3-70B 的 128k 标记的缓存大小)的情况下,传输引擎在 4×200 Gbps 和 8×400 Gbps 的网络配置下分别实现了 87 GB/s 和 190 GB/s 的带宽。这些速度分别比使用 TCP 协议快约 2.4 倍和 4.6 倍。该传输引擎的代码也将稍后开源,因为它是一个独立且基础的工具,可以在许多场景中使用(例如,它也用于 Moonshot AI 的检查点传输服务)。

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_架构_19

5.4.2 MOONCAKE 的带宽需求

MOONCAKE 的全局缓存池依赖于高效的节点间缓存传输,以隐藏缓存传输时间在 GPU 计算时间之内。我们通过模拟从 24 Gbps 到 400 Gbps 的一系列带宽,并在第 5.2.1 节中描述的合成工作负载下测量传输时间和 TTFT,来评估网络带宽对系统性能的影响。图 13a 显示,随着带宽的增加,请求的平均 TTFT 降低。当总通信带宽超过 100 Gbps 时,平均 TTFT 保持在 2 秒以下,显著低于重新计算基线的 TTFT。然而,当带宽低于 100 Gbps 时,系统性能显著下降。这表现为 TTFT 的急剧增加和明显的网络拥塞,如图 13b 所示,实际传输时间与理论传输时间之间存在显著差异。因此,我们建议最低网络带宽为 100 Gbps,以确保系统的最佳性能。

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_Mooncake_20

5.4.3 端到端延迟分解

MOONCAKE 中单个推理请求的延迟可以分解为五个部分:1)调度和排队时间;2)按层预填充时间;3)缓存传输时间;4)解码节点将缓存从 DRAM 加载到 HBM 所需的时间;5)解码时间。我们在前缀缓存比例为 0% 和 95% 的设置下实验性地分析了这五个部分的比例,如图 14 所示。首先,从图中可以看出,引入前缀缓存显著减少了预填充时间。具体来说,在输入长度为 128k 标记的情况下,前缀缓存将预填充时间减少了 92%。此外,MOONCAKE 引入的开销对系统的性能影响最小。调度、传输和加载缓存这些部分可以与模型推理异步进行,因此不会影响 MOONCAKE 的吞吐量。此外,由于这些开销而导致的 TTFT 增加小于通过前缀缓存实现的减少。即使考虑了开销,MOONCAKE 中的前缀缓存也可以将 TTFT 减少 86%,输入长度为 128k 标记。

Mooncake: Trading More Storage for Less Computation—A KVCache-centric 以KVCache为中心的架构用于服务LLM聊天机器人_KVCache 为中心的架构_21

5.5 P/D 比率

作为部署的 P/D 解耦系统,在本节中,我们探讨了不同的 P/D 比率对系统性能的影响。我们将 P/D 比率定义为预填充节点数与解码节点数的比率。使用由 16 个节点组成的集群,但具有不同的 P/D 比率,我们在第 5.2.1 节中描述的合成工作负载下测量了平均 TTFT 和 TBT。然后,我们计算了有效请求容量,如第 5.2.2 节中介绍的那样,将 TTFT 和 TBT 的阈值分别设置为 10 秒和 100 毫秒。增加预填充节点的数量可以减少 TTFT,但会增加 TBT,反之亦然(图 15b)。因此,我们需要在 TTFT 和 TBT 之间找到平衡。图 15a 表明,当 P/D 比率约为 1:1 时,MOONCAKE 实现了最高的有效请求容量,表明预填充和解码集群的负载相对平衡。我们还注意到,一些先前的工作提出了动态切换节点在预填充和解码之间的角色。然而,在实际部署中,我们发现在线流量的统计特性通常较为稳定。因此,我们选择固定 P/D 比率,同时持续监控预填充和解码集群的负载,只有在出现显著的负载波动时才切换节点角色。

6. 相关工作

人们已经投入了大量的努力,通过调度、内存管理和资源解耦来提高 LLM 服务系统的效率。生产级系统,如 FasterTransformer、TensorRT-LLM 和 DeepSpeed Inference,旨在显著提高吞吐量。Orca 采用迭代级调度,以促进各个阶段的并发处理,而 vLLM 则利用动态 KVCache 管理来优化内存。FlexGen、Sarathi-Serve 和 FastServe 纳入了创新的调度和交换策略,以有效地将工作负载分配到有限的硬件上,通常补充彼此的优化。进一步的优化导致了预填充和解码阶段的分离,从而导致了 MOONCAKE 的解耦架构。我们的 MOONCAKE 设计建立在这些发展之上,特别是从 vLLM 的开源社区中汲取灵感,我们对此深表感激。

前缀缓存也被广泛采用,以在多个请求之间重用 KVCache,减少 LLM 推理系统中的计算开销。Prompt Cache 预计算并存储在推理服务器上的常用文本 KVCache,便于其重用,并显著减少推理延迟。SGLang 利用 RadixAttention,它使用 radix 树结构中的最近最少使用(LRU)缓存,以高效地实现各种重用模式之间的自动共享。在这些方法中,CachedAttention 是与我们同时进行的工作,它提出了一个分层的 KV 缓存系统,利用成本效益高的内存和存储介质来容纳所有请求的 KVCache。MOONCAKE 的架构与 CachedAttention 有许多设计选择。然而,在长上下文推理中,KVCache 变得非常大,需要高容量和高效的数据传输,以及以 KVCache 为中心的全局调度。此外,MOONCAKE 不是一个独立的缓存服务,它结合了内存高效的缓存存储机制和缓存感知调度策略,进一步提高了前缀缓存的效率。在固定的容量下,每标记的缓存大小越小,缓存命中率越高。因此,正交技术,如 KVCache 压缩和 KVCache 友好的注意力架构,可以进一步增强我们的方法。

7. 结论

本文介绍了 MOONCAKE,这是一种以 KVCache 为中心的解耦架构,旨在高效地服务于 LLM,特别是在长上下文场景中。我们讨论了在平衡最大化整体有效吞吐量的目标的同时满足延迟相关的 SLO 要求所涉及的必要性、挑战和设计选择。