LLM Infer Infra 学习资料库

框架对比:vLLM 与 SGLang、LMCache 与 Mooncake

Serving 与性能 · 组件选型 · 推理过程动态图解 · LMCache + Mooncake 联合链路

这一页做两组对比:vLLM 和 SGLang 是同一层的推理引擎,比较它们怎样调度、怎样管理 GPU 上的 KV、怎样执行;LMCache 和 Mooncake 不在同一层,比较它们在 KV 的管理、存储和传输上各负责什么、怎样组合。对比基于资料使用的源码版本(vLLM f3871c3、SGLang 30dc2f9、LMCache ff9185d、Mooncake dd1217b),两边都在快速演进,新版本要重新核对。

先说结论:vLLM 和 SGLang 的核心思路越来越接近(连续批处理、分页 KV、前缀缓存、重叠调度都有),差别主要在前缀索引的数据结构、调度时是否考虑缓存、以及生态和扩展方式。LMCache 和 Mooncake 不是二选一:LMCache 懂“KV 是什么”,Mooncake 擅长“把字节可靠高速地存到集群里”,常见做法是把 Mooncake Store 作为 LMCache 的后端。

1. vLLM 与 SGLang:调度与执行

维度vLLM(V1 引擎)SGLang怎样理解差别
进程结构API 服务进程 + EngineCore 进程(调度和执行),多卡时再有 worker 进程TokenizerManager → Scheduler → 模型 worker → DetokenizerManager,多个进程通过 IPC 串起来都把 CPU 上的分词、调度和 GPU 执行拆开,减少互相阻塞
每轮选谁统一 token 预算:先满足正在运行的请求,剩余预算给等待队列;长 Prefill 自动切块可选调度策略:考虑缓存的(如最长前缀匹配 lpm)和不考虑缓存的(如 fcfs);同样支持 chunked prefillSGLang 可以优先调度能命中更长前缀的请求,提高复用;代价是可能牺牲先来先服务的公平性
显存不够时抢占:释放被抢占请求的 KV 块,之后重算同样有撤回(retract)请求和按缓存情况决定的准入都靠“重算”换回显存,抢占越多浪费越多
CPU 与 GPU 重叠可开启异步调度,让下一轮的调度和本轮 GPU 计算重叠重叠调度器:CPU 准备下一轮时 GPU 在算本轮(有关闭开关)Decode 每轮很短时,CPU 调度开销可能占到不小比例,重叠能明显提高 GPU 利用率
图优化torch.compile + CUDA Graph(分段和完整两种)CUDA Graph,也支持 torch.compile都是为减少小 kernel 的启动开销,主要帮 Decode
结构化输出 / 前端支持结构化输出后端起源于“结构化生成语言”,前端 DSL 和受约束解码是传统强项多轮、分支、受约束生成多的场景,SGLang 的前缀复用更容易发挥
分布式与 PDTP/PP/DP/EP;PD 分离通过 KV Connector(NIXL、LMCache、Mooncake 等)TP/PP/DP/EP、DP attention;PD 分离内置,传输后端可选 Mooncake、NIXL 等vLLM 走统一的 Connector 接口扩展;SGLang 把更多能力做成内置选项

2. vLLM 与 SGLang:GPU 上的 KV 管理

两者都用分页显存,区别在于“怎样找到可复用的前缀”:vLLM 给每个装满的块算一条 hash 链,用 hash 表查找;SGLang 用一棵基数树(radix tree),从根往下按 token 匹配。

维度vLLM:块 hash(APC)SGLang:RadixCache
索引结构hash 表:块 hash → 物理块;hash 包含父块 hash基数树:每个节点存一段 token 及其 KV 位置,根到节点的路径就是前缀
匹配粒度按块(默认 16 个 token),只匹配装满的块按 token 或按页(页大小可配置),可以匹配到更细的位置
部分重叠的前缀天然支持:前几个块 hash 相同就共享在分界处把节点拆成两段(split)
保护正在用的数据块的引用计数 ref_cnt节点的 lock_ref,从被引用的节点一直锁到根
淘汰引用为 0 的块按空闲队列顺序(近似 LRU)被重新分配时淘汰从 lock_ref = 0 的叶子节点里按最久未访问淘汰
分层缓存通过 KV Connector 接外部缓存(LMCache、Mooncake 等)HiCache:GPU、主机内存、外部存储三层,可接 Mooncake 等后端

基数树的工作过程(vLLM 的块 hash 过程见块管理器深入):

基数树rootlock=1
请求—
淘汰候选可淘汰:无
基数树root「系统提示 S + 问题 Q1」lock=1
请求请求 1 = S + Q1,没有命中,算完后插入树
淘汰候选可淘汰:无(请求 1 还在运行)
基数树root「S + Q1」lock=0
请求请求 1 结束,节点保留在树里
淘汰候选可淘汰:「S + Q1」
基数树root「S」lock=1└「Q1」lock=0└「Q2」lock=1
请求请求 2 = S + Q2:匹配到 S,节点在 S 处拆分,只算 Q2
淘汰候选可淘汰:「Q1」
基数树root「S」lock=1└「Q1」lock=0└「Q2」lock=1「T + Q3」lock=1
请求请求 3 = 另一个系统提示 T + Q3:没有命中,新开一个分支
淘汰候选可淘汰:「Q1」
基数树root「S」lock=1└「Q2」lock=1「T + Q3」lock=1
请求显存紧张:从 lock=0 的叶子里按最久未访问淘汰
淘汰候选「Q1」被淘汰,它的 KV 槽位被释放
  1. SGLang 用一棵基数树(radix tree)管理所有缓存的 KV。每个节点保存一段 token 和对应的 KV 位置;从根到某个节点的路径就是一段完整前缀。根节点永远锁定。
  2. 请求 1 没有命中任何前缀,算完后把“S + Q1”整段作为一个节点插入。运行期间节点的 lock_ref = 1,不能被淘汰。
  3. 请求 1 结束,lock_ref 归零,但节点和 KV 仍留在树里,等待以后复用。
  4. 请求 2 的前缀 S 和已有节点部分相同:在 S 和 Q1 的分界处把节点拆成两段(_split_node),S 被两个请求共享,只需要为 Q2 计算新的 KV。正在使用的路径都会被加锁。
  5. 请求 3 的前缀完全不同,从根节点开出新分支。树可以同时保存很多不同的前缀。
  6. 需要空间时,从“lock_ref = 0 的叶子节点”里按最后访问时间淘汰(用堆找最旧的)。叶子被删后,如果父节点也变成没被锁的叶子,下一轮也可能被淘汰。正在使用的路径永远不会被删。

面试怎么答“哪个好”:没有绝对的好坏。基数树对大量共享前缀、多轮分支对话的匹配更细、更直观;块 hash 实现简单、天然适合按块管理和跨进程传输(hash 可以直接作为外部缓存的 key)。真正的性能差异要在同样模型、同样负载、同样硬件下测,而且要分开看前缀命中、调度和 kernel 的贡献。

3. LMCache 与 Mooncake:各管哪一层

LMCache 与 Mooncake 的分层关系

维度LMCacheMooncake
定位推理引擎和存储之间的 KV 管理层以 KV 为中心的分布式存储与传输系统(Store + Transfer Engine)
懂不懂 KV 语义懂:按 chunk(常用 256 token)切分、算前缀 hash、区分 rank 和组、处理布局基本不懂:Store 看到的是 key 和字节,TE 看到的是地址和长度
和引擎的接口vLLM KV Connector、SGLang 集成;负责 lookup、retrieve、store 与设备拷贝被上层调用:LMCache 后端、SGLang HiCache 后端、vLLM Connector、PD 交接通道
元数据每个 LMCache 服务管理自己的 L1;多实例可选 Coordinator中心化 Master 管对象位置、副本、租约;可部署高可用
存储介质L1 主机内存(自己管);L2 交给适配器:本地磁盘、Redis、Mooncake、NIXL、对象存储等各节点贡献的内存段为主,也可下沉到本地盘、DFS 等
写入可见性L1 先 staging,填完再发布PutStart 分配 → 写数据 → PutEnd 发布
读保护L1 读写保留;L2 适配器层的锁约定读租约(默认 10 秒)、soft/hard pin
淘汰L1 按策略(如 LRU)淘汰;不淘汰正在读写的对象用量超过高水位(默认 90%)后淘汰约 5%,跳过有租约、有 pin 的对象
传输GPU ↔ L1 的设备拷贝;L2 传输交给后端Transfer Engine:RDMA 多网卡、按拓扑选路、slice 切分、失败重试
容错主要依赖后端;失败时回退重算多副本、Master 高可用;副本全丢时上层回退重算
额外能力CacheBlend(非前缀复用)、CacheGen(压缩)、逐层加载、可观测性PD 交接、Conductor(全局前缀索引)、EP 通信、权重传输等

3.1 怎样选、怎样组合

场景推荐原因
单机多轮对话,主机内存够用LMCache(L1 主机内存)或引擎自带的分层缓存不需要分布式存储,少一层复杂度
多台机器共享长文档、长系统提示LMCache + Mooncake Store 作为 L2LMCache 处理语义和设备拷贝,Mooncake 提供跨节点内存池和 RDMA
SGLang 部署HiCache + Mooncake 后端SGLang 自己管理分层,直接用 Mooncake 做外部层
PD 分离,只需要把本次请求的 KV 交给 DecodeMooncake Transfer Engine 或 NIXL这是一次性的点对点传输,不需要对象存储
非前缀片段复用(RAG 文档顺序变化)LMCache CacheBlend需要选择性重算,属于 KV 语义层的能力,要评估质量

完整的保存与恢复链路、三层保护的区别,见 LMCache + Mooncake 联合链路。

4. 更多常见对比

面试和选型中还经常遇到下面几组“同类方案怎么选”的问题。

4.1 四种并行方式(动态演示见进阶动态图解)

方式切什么通信适合主要问题
TP 张量并行每层的权重矩阵每层 all-reduce,频繁且在关键路径上单卡放不下、需要降低单请求延迟;机内 NVLink跨机做 TP 通信代价很高
PP 流水线并行按层分段段与段之间传激活,量小模型特别大、跨机部署流水线气泡;单请求延迟不降
DP 数据并行不切模型,复制多份推理时几乎没有提高总吞吐每份都要完整权重;前缀缓存分散在各副本
EP 专家并行MoE 的专家每个 MoE 层两次 all-to-all大 MoE 模型负载不均、网络敏感、故障影响面大

4.2 PD 分离与混合部署

维度混合部署 + chunked prefillPD 分离
Decode 受 Prefill 干扰有,但被切块后变小几乎没有
额外开销无每个请求传一次 KV,需要高速网络
扩缩容整体扩缩Prefill 池、Decode 池分别扩缩,可用不同硬件
复杂度低高:路由、传输、故障处理都更复杂
适合中小规模、输入不太长大规模、长输入、对 ITL 的 P99 要求严格

4.3 SGLang HiCache 与 LMCache

维度HiCacheLMCache
位置SGLang 内置,和 RadixCache 一体独立的缓存层,可服务 vLLM、SGLang
层级命名GPU 为 L1、主机内存为 L2、外部存储为 L3主机内存为 L1、外部后端为 L2
和调度的结合直接参与 SGLang 的前缀匹配和调度通过 Connector 接口告诉引擎能复用多少
部署随 SGLang 进程可作为独立进程(MP 模式),引擎重启后缓存仍在
外部存储Mooncake 等后端多种 L2 适配器,含 Mooncake

4.4 引擎内前缀缓存与外部 KV 缓存

维度引擎内(APC、RadixCache)外部(LMCache、Mooncake 等)
容量受 GPU 显存限制主机内存、远端内存、磁盘,可大很多
命中后的成本几乎为零,直接用要加载:查询 + 网络 + H2D
跨实例共享不能可以
进程重启缓存丢失可以保留
结论两者互补:引擎内缓存负责最热的部分,外部缓存负责“放不下、跨实例、要保留”的部分;实验时要分开统计两者的命中

输入主题、术语或问题