LLM调度的核心KVCache
Mooncake作为Moonshot AI提供的Kimi服务的后端平台,提出了一种以键值缓存(KVCache)为中心的解耦架构,旨在优化长上下文场景下的服务效能,并在高负载情况下保持服务水平目标(SLOs)。
Mooncake架构通过解耦预填充和解码阶段,并以KVCache为中心进行调度和优化,有效地提升了LLM服务在长上下文和高负载场景下的性能。通过实验验证,Mooncake在保持SLOs的同时,相比基线方法,吞吐量提升了高达525%,并能在实际工作负载下处理75%以上的请求。
Mooncake解决的问题
-
资源利用不均与服务效能
Mooncake的KVCache中心调度器,负责平衡最大整体有效吞吐量和满足延迟相关的SLOs。通过解耦预填充(prefill)和解码(decoding)集群,以及利用GPU集群中未充分利用的CPU、DRAM和SSD资源,实现了KVCache的解耦缓存,从而优化了资源利用率和整体吞吐量。
-
长上下文处理效率
Mooncake采用分块流水线并行(CPP)机制,对于单个长上下文请求,Mooncake将输入token分割成小块,每个小块不超过预设的阈值(例如1000个token),并在多个节点上并行处理,以减少首个token时间(TTFT)。
-
高负载下的请求调度
Mooncake开发了基于预测的早期拒绝策略,在高负载情况下,通过预测未来负载和生成长度,提前拒绝某些请求,以避免在预填充阶段后无可用解码槽位时的资源浪费。
Mooncake架构

Mooncake主要包括以下组件:
-
KVCache中心调度器(Conductor)
-
预填充实例
-
解码实例
-
分布式KVCache池等组件。
每个请求由Conductor调度,选择预填充和解码实例,并按照以下步骤执行:
-
KVCache重用:预填充节点加载可重用的前缀缓存到GPU内存中,以启动请求。 -
增量预填充:预填充节点完成预填充阶段,并将新生成的增量KVCache存储回CPU内存。 -
KVCache传输:Messenger服务管理并传输这些缓存,将每层生成的KVCache流式传输到目标解码节点的CPU内存中。 -
解码:在解码节点的CPU DRAM中接收到所有KVCache后,请求以连续批处理的方式加入下一个批次。
分块流水线并行(CPP)

Mooncake利用CPP机制处理长上下文请求。具体步骤如下:
-
输入分割:将请求的输入令牌分割成小块,每个块不超过预设的阈值。 -
并行处理:不同块的令牌可以在不同节点上同时处理,实现并行化。 -
跨节点通信:仅在流水线阶段边界处需要跨节点通信,与计算重叠,减少网络资源竞争。 -
层级预填充:KVCache的加载和存储操作在每一层的注意力计算前后异步执行,以减少传输开销。

KVCache中心调度算法

Mooncake的KVCache中心调度算法如下:
-
计算块键:将请求的输入令牌分成多个块,并为每个块计算哈希键。 -
寻找最佳前缀匹配:比较请求的块键与每个预填充实例的缓存键,以确定前缀匹配长度。 -
估计预填充执行时间:根据请求长度和前缀长度估计预填充阶段的执行时间。 -
选择实例:将请求分配给具有最短TTFT的实例,并更新该实例的缓存和队列时间。 -
负载平衡:如果最佳远程前缀匹配长度不超过当前本地可重用前缀的阈值倍数,则触发KVCache的热斑点迁移。
过载场景下的调度
在系统过载时,Mooncake采用早期拒绝策略,具体步骤如下:
-
系统负载评估:基于预填充和解码池的负载,决定是否接受请求。 -
早期拒绝:在预填充阶段前评估解码实例的负载,如果负载过高,则拒绝请求,避免资源浪费。 -
基于预测的早期拒绝:预测解码实例在未来一段时间内的负载,基于预测结果决定是否接受请求,以减少负载波动。
Mooncake与VLLM对比
模拟长上下文对两个框架的影响。

-
长上下文请求显着扰乱了 vLLM 的解码阶段。 为了解决这个问题,vLLM 单独处理请求,而不是批量处理。
-
Mooncake采用了批处理,但其两阶段分解设计有效地减少了预填充阶段对解码阶段的影响,确保它永远不会破坏TBT SLO
-
与 vLLM 相比,Mooncake 表现出显着更高的吞吐量,增强幅度从 50% 到 525%,同时遵守相同的 TTFT 和 TBT SLO 限制。