来源:互联网 更新时间:2026-08-15 14:32
Mooncake 是 Kimi 背后的服务平台,而 Kimi 来自月之暗面(Moonshot AI),一家国内领先的大语言模型服务商。简单来说,Mooncake 是一种以 KVCache 为中心的解耦架构——它把预填充(prefill)和解码集群彻底分开,同时充分利用 GPU 集群中平时闲置的 CPU、DRAM 和 SSD 资源,搭建了一个解耦的 KVCache 缓存层。它的核心是一个同样以 KVCache 为中心的调度器,目标是在满足延迟类服务级别目标(SLOs)的前提下,最大化整体的有效吞吐量。不过,与那种假设所有请求都能被照单全收的传统研究不同,Mooncake 在真正的高负载场景下同样面临不小的挑战。
为了应对这些挑战,开发团队设计了一套基于预测的早期拒绝策略。实验结果表明,这套策略在长上下文场景中效果相当突出——相比基准方法,在特定模拟场景下,Mooncake 的吞吐量能提升最多 525%,而且始终遵守 SLOs。在实际工作负载中,Mooncake 的创新架构让 Kimi 能够多处理 75% 的请求。
大语言模型(LLM)在各行各业迅速普及,服务端的工作负载也变得极度多样化。输入/输出长度、到达频率、分布形态各不相同,更关键的是,它们对服务级别目标(SLOs)的要求也千差万别。作为一家模型即服务(MaaS)提供商,月之暗面面临的核心优化问题相当复杂——约束条件来自不同层次的 SLOs(主要涉及延迟,比如首个令牌时间 TTFT 和令牌间时间 TBT),优化目标则是最大化整体有效吞吐量,这直接决定了收入。
要实现这个目标,前提是把 GPU 集群中可用的各种资源都用足。虽然现在的 GPU 服务器通常以高度集成的节点形式提供(比如 DGX/HGX 超级计算机),但有必要把它们解耦、重组为几个分工明确的资源池,每个池针对不同但彼此协作的目标进行优化。举个例子,很多研究人员已经建议把预填充服务器和解码服务器分开,因为这两个阶段的计算特性差异巨大——KVCache 在请求从预填充服务器转移到解码服务器时需要转换。顺着这个思路,我们发现 KVCache 的调度其实是 LLM 服务调度的核心。要提高整体吞吐量,通常有两条路:一是尽可能多地复用 KVCache,减少重复计算;二是最大化每个批次中的令牌数量,提高模型浮点运算利用率(MFU)。但问题在于,从远程位置复用 KVCache 会延长 TTFT,而大批量处理又会导致 TBT 变大。想同时用好这两条优化路径,很可能就会违反延迟相关的 SLOs。
所以,我们最终提出了一种以 KVCache 为中心的解耦设计来做调度和优化。图 1 展示的就是这套架构,名为 Mooncake。对于每个请求,全局调度器(Conductor)需要选出一对预填充实例和解码实例,然后按以下步骤调度:首先,把尽可能多的可复用 KVCache 转移到选定的预填充实例;其次,按块/层完成预填充阶段,同时把输出 KVCache 持续流式传输到对应的解码实例;最后,加载 KVCache 并把请求加到解码实例的连续批处理中,开始生成输出。流程听起来简单,但选择策略因为各种约束而变得相当复杂。在预填充阶段,核心目标是尽可能复用 KVCache 避免冗余计算,但等待存储在低层级存储上的 KVCache 又可能违反 TTFT SLO。而且,对 KVCache 服务器的需求一高,网络拥塞就会加剧,等待时间也随之延长。因此,Conductor 还得预测 KVCache 块的未来使用情况,并相应地执行交换、复制等调度操作——最热的块要复制到多个节点以免获取拥塞,最冷的块则要交换出去以降低保留成本。预填充调度还受限于预填充节点内 DRAM 空间的可用性,尤其是当大部分内存都留给了全局 KVCache 池时。
相比之下,解码阶段的优化目标和限制完全不同。目标是尽可能多地聚合解码批次中的令牌以提高 MFU,但这个目标不仅受 TBT SLO 制约,还受 VRAM 中能容纳的聚合 KVCache 总量限制。更重要的是,现有 LLM 服务研究都假设资源充足,只想着提高资源利用率;而现实情况是 GPU/翻跟斗供应有限,很多 MaaS 提供商面对的是严重的过载问题,高峰期尤其突出。在这种情况下做调度,会带来现有研究从未探讨过的独特挑战。比如,我们需要预测未来的负载,并在预填充阶段之后、如果发现没有可用的解码插槽,就提前拒绝某些请求以节省计算资源。但直接实现这种早期拒绝策略,反而可能引发过载波动。这就迫使我们必须预测特定查询的生成长度,并进行短期的整体负载预测,才能做出更好的拒绝决策。与此同时,还需要对不同请求的优先级进行分类,实现基于优先级的调度。在本文中,我们把这些问题统称为“面向过载的调度”,并展示了初步的研究成果。
先快速梳理一下 Mooncake 的整体架构,包括主要组件和处理请求的典型工作流,然后重点说明实现过程中那些当前研究尚未覆盖的设计选择。
首先要实现一个独立的预填充节点池,让它能无缝处理上下文长度的动态分布。我们采用了一种分块流水线并行(CPP)机制,把单个请求的处理扩展到多个节点——这对减少长上下文输入的 TTFT 来说是必须的。与传统基于序列并行(SP)的方案相比,CPP 减少了网络消耗,也简化了对频繁弹性扩展的依赖。这一机制配合层级预填充,还能让 KVCache 的流传输与计算重叠,进一步降低延迟。
接着是核心的以 KVCache 为中心的请求调度算法,它要平衡实例负载和以 TTFT、TBT SLOs 衡量的用户体验。这里面包含一种基于启发式的自动热点迁移方案,不需要精确预测未来 KVCache 使用情况,就能自动复制热点 KVCache 块。实验表明,这种缓存感知调度在实际场景中能显著降低 TTFT。
在使用公共数据集、模拟数据和实际工作负载的端到端实验中,Mooncake 在长上下文场景中表现优异。与基线方法相比,在满足 SLOs 的前提下,吞吐量最多提高了 525%。在实际工作负载下,Mooncake 让 Kimi 能够多处理 75% 的请求。
最后,与假设所有请求都将被处理的现有 LLM 服务研究不同——因为 Kimi 的用户请求增长太快,Mooncake 几乎一直处在过载状态——Mooncake 的调度涉及根据系统负载决定是否接受或拒绝传入请求。§6 中讨论了我们实施的独特早期拒绝策略,它在过载场景中减少了浪费的计算资源,还进一步探讨了由直接早期拒绝引起的负载波动问题,以及如何通过预测未来负载来缓解这一现象。
Mooncake 目前是 Kimi 服务的主力平台,已经成功应对了指数量级的工作负载增长,证明了它在扩展到大型且高度过载的工作负载方面的有效性。当然,还有很多问题值得继续探索,这些未来方向也一并包含在本文中。
现代大语言模型(LLM)基于 Transformer 架构,利用注意力机制和多层感知器(MLP)来处理输入。流行的基于 Transformer 的模型(如 GPT、LLaMA)采用仅解码结构。每个推理请求在逻辑上分为两个阶段:预填充阶段和解码阶段。预填充阶段并行处理所有输入令牌,生成第一个输出令牌的同时,存储已计算的键和值的中间结果,即 KVCache。解码阶段则利用这个 KVCache 自回归地生成新令牌,并把新计算的键和值不断追加到 KVCache 中。
预填充阶段能同时处理输入令牌,通常是计算密集型的(短请求除外)。由于注意力网络的计算复杂度随输入长度二次增长,而 MLP 是线性增长,预填充阶段的计算时间通常随输入长度超线性增长(如图 2 左侧所示)。相反,解码阶段受自回归生成限制,每批次一次只能处理一个令牌,因此它是内存受限的,计算时间随批次大小次线性增加(如图 2 右侧所示)。解码阶段广泛使用的一种优化是连续批处理——每次迭代前,调度器检查所有请求的状态,把新到达的请求加入批次的预填充阶段,同时移除已完成的请求。
由于预填充和解码阶段的不同特性,MaaS 提供商设置了不同的指标来衡量相应的 SLOs。预填充阶段主要关注从请求到达到生成第一个令牌之间的延迟,即首个令牌时间(TTFT)。解码阶段关注的是同一请求连续令牌生成之间的延迟,即令牌间时间(TBT)。作为 MaaS 提供商,确保满足服务协议定义的 SLO 指标是至关重要的。例如,TTFTP 90 = 4× 表示 90% 的推理请求的 TTFT 不会超过在相同条件下单个请求运行时间的四倍。在本文的端到端实验中,我们设定 TTFTP 90 = 10× 和 TBTP 90 = 5×。实际部署中,我们采用固定的 TTFT 和 TBT SLOs。一旦监控检测到未满足的 SLOs,要么增加推理资源,要么拒绝一些传入请求。然而,目前 GPU 供应紧张,弹性扩展推理集群通常不可行。因此,决定拒绝哪些请求就成了面向过载调度的核心问题。
我们的主要目标是在遵守 SLOs 的同时最大化整体吞吐量,其他研究中将其称为“有效吞吐量”(goodput)。我们的方法不同之处在于,只有完全完成执行的请求才计入有效吞吐量;否则,所有先前消耗/生成的令牌都不计数,对应的资源就算浪费了。换句话说,某个请求如果无法在 SLO 下完成全部执行,就应该尽早拒绝它。实现这一目标不仅需要优化预填充和解码阶段的架构,还需要开发预测短期未来负载的能力。
如图 1 所示,Mooncake 采用了解耦架构,不仅把预填充节点与解码节点分开,还把 GPU 集群的 CPU、DRAM、SSD 和 RDMA 资源组合起来,实现了一个解耦的 KVCache。这个解耦缓存利用平时未充分利用的资源,提供了充足的缓存容量和传输带宽,从而实现高效的近 GPU 前缀缓存,而且无需额外成本。
图 3 展示了 KVCache 块的存储和传输逻辑。在 CPU 内存中,KVCache 以分页块的形式存储。根据请求模式,可以使用 LRU、LFU 或基于请求特性的缓存淘汰算法。这些 KVCache 块在 CPU 和 GPU 之间的传输由一个名为 Messenger 的独立(GPUDirect)基于 RDMA 的组件处理。这种架构还使我们能够向外部用户提供上下文缓存 API,以提高 KVCache 的重用率。
为了调度所有这些解耦的组件,Mooncake 在其核心实现了一个名为 Conductor 的全局调度器。Conductor 负责根据当前的 KVCache 分布和工作负载分配请求。如果对未来推理有利,它还会复制或交换某些 KVCache 块。图 4 展示了一个请求的典型工作流程:一旦标记完成,Conductor 选择一对预填充节点和一个解码节点,然后开始包括四个步骤的工作流程。
选定的预填充节点(组)接收一个请求,其中包括原始输入、可重用前缀缓存的块 ID 和分配给请求的完整缓存块 ID。它根据前缀缓存块 ID 从远程 CPU 内存加载前缀缓存到 GPU 内存中,以启动请求。如果不存在前缀缓存,则跳过此步骤。此选择平衡了三个目标:尽可能多地重用 KVCache、平衡不同预填充节点的工作负载,并保证 TTFT SLO。这导致了以 KVCache 为中心的调度,进一步讨论见 §5。
预填充节点(组)使用前缀缓存完成预填充阶段,并将新生成的增量 KVCache 存储回 CPU 内存。如果未缓存的输入令牌数量超过一定阈值(prefill_chunk),则预填充阶段被分成多个块并以流水线方式执行。选择此阈值以充分利用相应 GPU 的计算能力,通常超过 1000 个令牌。使用分块但仍解耦的预填充节点的原因见 §4.1。
上述的 Messenger 服务部署在每个节点中,以管理和传输这些缓存。每个 Messenger 作为其各自推理实例中的独立进程运行,接收信号以促进高速、跨机器的 KVCache 传输。此步骤异步执行,并与上述增量预填充步骤重叠——流式传输由每个模型层生成的 KVCache 到目标解码节点的 CPU 内存中,以减少等待时间。图 4 展示了推理实例的工作流程。(*)对于预填充实例,KVCache 层的加载和存储操作逐层进行,并与预填充计算并行,以减轻传输开销。(†)对于解码实例,异步加载与 GPU 解码同时进行,以防止 GPU 空闲时间。
在解码节点的 CPU DRAM 中接收到所有 KVCache 后,请求以连续批处理方式加入下一个批次。Conductor 根据解码节点的当前负载预先选择解码节点,以确保其不违反 TBT SLO。然而,本地调度器会再次检查该 SLO,因为预填充阶段后的预期负载可能已发生变化。这种双重检查可能导致请求被拒绝,在这种情况下,相应的预填充成本将被浪费。
腾讯ima怎么把微信内容一键导入知识库?
黄金价格不断创新高!黄金稳定币XAU、PAXG市值达11亿美元
CC币价格预测(2026-2035):Canton币今日价格走势+长期价格预测
新浪互联网热点小时报丨2026年07月26日16时_今日实时互联网热点速递
新浪机器学习热点小时报丨2026年07月25日18时_今日实时机器学习热点速递
2026鸣潮账号交易安全指南:五大交易平台对比与风险避坑分析
腾讯ima怎么创建共享知识库?
今日比特币暴涨分析:Metaplanet的比特币BTC投资推动股价上涨17%
蚂蚁庄园今日答案7月21日(今日已更新) 蚂蚁庄园今天正确答案是什么呢
新浪人工智能热点小时报丨2026年07月30日18时_今日实时人工智能热点速递
抖音怎么取消申请退货退款?抖音上取消退货怎么操作
比特币(BTC)核心周期指标复刻历史走势 价格或跌破5.8万美元关键支撑位
Windy卫星云图怎么看?云层变化识别技巧
9条破亿视频,新号涨粉百万,过去半年谁在制造AI爆款?
短剧《史上最强洪荒修为》剧情介绍
kimi提示词专家使用方法新手指南
Celestia价格预测2026-2032:TIA币能否引领山寨币上涨行情?历史价格回顾
如何修复Edge浏览器无法通过微软账号进行身份验证?
原神霜月三处月灵龛具体位置汇总
五菱星光L六座新能源SUV上市:三版可选,中配12.28
手机号码测吉凶
本站所有软件,都由网友上传,如有侵犯你的版权,请发邮件haolingcc@hotmail.com 联系删除。 版权所有 Copyright@2012-2013 haoling.cc