SGLang 全局 KV 缓存重用详解 | AI生成和翻译

Home 2026.06

问题: 上述 SGLang 技术描述是什么意思?请解释上文提到的全局 KV 缓存复用、内存分配器调整以及性能结果。

回答:

这描述的是 SGLang 的上下文并行(CP)+ 全局 KV 缓存重新分片特性——一种在多个 GPU 秩之间共享 KV 缓存而非每个秩维护独立缓存的方式。下面逐层解析。


背景:正在解决什么问题?

在标准 LLM 服务中,KV 缓存(注意力机制中具体化的 K 和 V 张量)按每个 GPU 秩本地存储。使用张量并行(TP=8)时,每个秩持有其自身序列分片的 KV 缓存分片。这意味着:

目标是使 KV 缓存能够在 CP 秩之间全局复用


第 1 部分:Radix 缓存 → 全局缓存树

SGLang 现有的前缀缓存使用Radix 树(基于 token 序列的字典树):

Root
├── [sys_prompt_tokens] → Node A (rc=2, last_access=T1)
│   ├── [user_tokens_1] → Node B
│   └── [user_tokens_2] → Node C

每个节点存储:

CP 扩展为每个页面增加了一个字段:CP Owner(哪个秩持有此 KV 页面)。

@dataclass
class KVPage:
    token_ids: List[int]
    kv_data: Tensor        # 实际的 K,V 值
    cp_owner: int          # 新增:哪个 CP 秩拥有此页面
    ref_count: int
    last_access: float

现在 Radix 树变成了一个全局索引——每个秩都能看到整棵树,并知道:

这保持了 SPMD(单程序多数据)设计:每个秩运行相同的树插入/查找代码。CP Owner Manager 决定放置策略(复制冗余页面,分片唯一页面)。


第 2 部分:驱逐——领导秩模式

驱逐是 SPMD 唯一失效的地方,因为不同秩的内存压力不同。解决方案:

R0(领导)遍历全局树
    → 选择要驱逐的页面(LRU 策略)
    → 通过 AllReduce/Broadcast 在 CP 组内广播决策
所有秩执行相同的驱逐操作
    → 树在所有秩之间保持一致

这是一种经典的通过单一领导者实现分布式共识模式——简单、正确,避免了分裂脑。缺点是 R0 负载略高,但驱逐不频繁,因此可以接受。


第 3 部分:内存分配器——集体分配

当 CP 沿序列维度拆分序列时,每个秩的 token 数量是不均匀的(填充或参差不齐的批次)。因此:

Rank 0: 1024 tokens → 需要 N 个页面
Rank 1: 987 tokens  → 需要 M 个页面

在分配之前,它们进行集体通信all_reduce 自由页面数量):

local_free = allocator.free_pages()
global_min_free = dist.all_reduce(local_free, op=MIN)
if global_min_free < required:
    trigger_eviction()
    # 重复直到所有秩都有足够空间

然后分配逻辑有 3 种情况:

1. 本地缓存命中    → 无操作,直接复用
2. 远程缓存命中    → 分配本地页面,从远程秩拉取 KV
3. 缓存未命中      → 分配并从头计算

关键洞察:这在页面抽象层面上操作,因此与以下因素无关:


第 4 部分:性能数据(DeepSeek 235B 在 H100 上)

配置 TTFT(p50) 说明
TP=8, EP=8(基线) 631ms 标准配置
Attn CP=2, MoE DP=2, EP=4 452ms -28%
Attn CP=2, EP=8 ~630ms 尚未改善
2节点, 16xH100, 32K 序列 764ms 弱扩展,不理想

为什么 CP=2 + EP=4 胜出:

  1. CP 减少了注意力通信——每个秩处理一半序列,因此注意力全连接更小
  2. EP=4(更小的专家并行)——MoE 负载不均衡随着 EP 秩增加而恶化;EP=4 以更小的偏斜分布专家

为什么 CP=2 + EP=8 尚未改善:通信减少的代码路径尚未合并——CP 开销抵消了收益。

为什么 2节点 32K 是 764ms(而非 ~631ms):KV 缓存 all-gather 仍在关键路径上——通信尚未与计算重叠。


第 5 部分:KV 缓存重新分片——核心优势

重新分片 = 当请求命中由不同 CP 秩拥有的缓存 KV 页面时,不是重新计算,而是拉取并重新分发该页面。

结果(TP=4,不同 CP):

指标 效果
精度 无变化(完全相同值)
KV 缓存内存使用 -50%(跨秩去重)
缓存命中率 +50% 更多可能命中
8K 吞吐量 -7%(all-gather 开销)
16K 吞吐量 -21%(80% 来自 KV all-gather,20% 来自调度器)

16K 的分解很重要:

因此,重叠后的理论稳态开销仅为约 4%——那就是调度器成本。


总结心智模型

CP 之前:
  Rank 0: [KV_A, KV_B, ...]   ← 隔离
  Rank 1: [KV_C, KV_D, ...]   ← 隔离

全局 KV 重新分片之后:
  全局 Radix 树(所有秩可见):
    prefix_1 → page_id=42, cp_owner=0
    prefix_2 → page_id=43, cp_owner=1

  任何秩都可以通过从拥有秩获取来服务任何前缀
  → 内存减少 50%(无冗余复制)
  → 对于长上下文服务,全局缓存命中率显著提升

这本质上是在 GPU HBM 之上构建一个分布式 KV 存储(类似于 Redis Cluster,但用于注意力 KV 张量,具有 LRU 驱逐和前缀感知路由),并直接集成到 SGLang 的调度器中。


Back Donate