‹ 返回博客‹ 返回博客

目录

SGLang 中的弹性专家并行扩展:使用 NIXL 扩容在线 MoE 部署Yoray Zack — NVIDIA 高级软件架构师、SGLang 贡献者2026 年 10 月 21 日

推理部署在变化的负载下运行,必须在保持吞吐量和延迟目标的同时调整容量。对于大型混合专家(MoE)模型,标准选项是水平扩展(增加另一个完整副本)和垂直扩展(以更宽的专家并行拓扑重启部署)。

水平扩展保持当前服务运行,但会增加完整的模型占用。垂直扩展可以用更小的增量达到所需拓扑,但需要重建分布式状态、重新加载模型并预热新部署。

弹性扩容基于恢复流程中已实现的原则。在恢复中,活动成员会意外变化;而在扩容中,变化是计划内的,新的 GPU rank 在运行时加入。在下面的示例中,一个 20 GPU 的部署通过增加四个 rank 扩展到 24 GPU,而无需替换正在运行的部署。

Comparison of horizontal scaling, restart-based vertical scaling, and live Elastic EP scaling from 20 to 24 GPUs.

图 1:一个说明性的 20→24 GPU 示例。弹性 EP 扩容向正在运行的部署增加四个 rank,而不是分配另一个 20 GPU 副本或替换作业。

摘要

  • 弹性 EP 扩容让 MoE 模型能够以细粒度增量增加 GPU,而无需部署完整副本或重启正在运行的部署。

  • max_ep_size 定义了部署可达到的最大 EP 拓扑。元数据和通信缓冲区容量在启动时预留,而额外的 GPU rank 仅在需要时启动。

  • 在报告的对比中,弹性 EP 扩容完成首个请求的速度比重启快 5.3×–8.2×。

扩容如何建立在恢复机制之上

在每次 MoE 前向计算中,token 激活会传输到拥有所选专家的 rank,输出则返回其源 rank。SGLang 的 大规模 EP 工作 解释了为什么这条专家分发路径对高并发和长上下文服务很重要。使用数据并行(DP)注意力时,每个逻辑 DP worker 保留自己的调度器和 KV 缓存,而专家层则跨 EP 拓扑通信。

运行时扩容直接建立在 SGLang 的 弹性 EP 故障恢复工作之上。两者都使用活动/非活动成员关系、Mooncake 进程组(Mooncake PG)准入以及前向结束时的过渡钩子。恢复将 rank 带回现有槽位及其原始进程组。扩容则激活最大尺寸 active_ranks 向量中未使用的尾部槽位,并准入加入的 rank。

一个约束塑造了该设计:启动时的进程组是静态的。因此,原始 rank 和每个加入组保持固定的张量并行(TP)和引导组,而 Mooncake WORLD 和逻辑 EP 成员关系在其上增长。

EP4 to EP6 membership expansion with fixed launch groups, Mooncake WORLD, and NIXL peers.

图 2:EP4→EP6 保持原始四 rank 启动组不变,将两个加入 rank 准入 Mooncake WORLD,并扩展 NIXL 的目标对等集合。

一个逻辑部署,三层协同

  1. SGLang 拥有服务控制平面。 它等待请求的加入 rank,分别跟踪 pending_ep_size 和 effective_ep_size, 在前向结束时安装目标专家和 DP 状态,并且仅在提交后暴露新的调度器槽位。

  2. Mooncake PG 实现弹性成员关系和同步。 其可扩展的 WORLD 准入加入者,并提供覆盖现有成员和加入者的屏障。SGLang 还使用 Mooncake PG 集合通信和 P2P 来协调扩容后的 EPLB。

  3. NIXL 提供专家数据平面。 NIXL EP 在每次 MoE 前向中分发 token 激活并合并专家输出。SGLang 的集成位于 NIXL 调度器.

中。随着 SGLang 扩展 EP 组,NIXL 保留已建立的对等连接。在 EP4→EP6 中,原始 rank 保留现有连接并添加 rank 4 和 5;加入者连接到 EP6 对等集合。SGLang 预先为 max_ep_size 配置 NIXL 元数据和 RDMA 缓冲区,而最初只连接活动 rank。连接仍然是惰性完成的,因此第一次更宽的分发可能包含一些设置成本。

将 max_ep_size 设置为部署预期达到的最大拓扑。更高的上限会在活动 GPU 上预留更多通信缓冲区内存,从而为 KV 缓存留下更少内存。

在线 EP 组如何增长

在高层次上,SGLang 先准备加入者,然后提交更宽的拓扑:

  1. 预留上限。 主节点通过 max_ep_size分配元数据和通信缓冲区容量。非活动槽位不会启动进程或占用 GPU。

  2. 启动加入的 rank。 外部编排器分配 GPU 并启动它们,而现有 EP 组继续服务。

  3. 准入并提交。 SGLang 等待完整的请求 rank 范围,扩展 Mooncake WORLD, 安装目标活动 rank、专家、DP 和 NIXL 状态,并同步每个 rank。启用 CUDA 图时,rank 会在提交新尺寸之前重新捕获它们。只有到那时, commit_scale() 才会推进有效尺寸。

  4. 路由并重新平衡。 数据并行控制器暴露新的逻辑 worker。NIXL 执行第一次更宽的专家分发,之后 EPLB 可以重新分配专家。

加入的 rank 进入 Mooncake WORLD后,尚不支持自动回滚;最终化期间的失败可能需要重启部署。

衡量过渡过程

我们使用 DeepSeek-V3-Lite FP8 在 8×H100 上对比了 Elastic EP Scaling 与重启。对于 Elastic EP Scaling,加入者在后台初始化,而现有部署继续提供服务。重启计时在源部署终止之前开始。在多次重复的 Elastic 运行中,每次过渡都已完成并通过扩容后的 GSM8K 验证。图 3 报告了 Elastic 的平均时间,以及具有相同 CUDA 图捕获范围的重启基线。

端点是在就绪后发出的短金丝雀请求。Elastic 就绪意味着在目标规模下 /is_scaling_elastic_ep 报告 serving_expanded ;重启就绪意味着 /health_generate 返回 HTTP 200。Elastic 金丝雀请求针对新的逻辑 DP rank,而重启使用轮询路由。

Time to the first completed request after Elastic EP scale-up versus restart.

图 3:从扩容或重启请求到目标拓扑上首个完成请求的时间。Elastic 柱状图显示重复运行的平均值;重启柱状图显示对比基线。CUDA 图行捕获了直至批次 16 的五个完整解码形状。

在拓扑过渡期间,token 交付会暂停。图 3 测量从扩容请求到扩展部署上首个完成请求的时间,包括任何首次使用的连接建立。

路线图

分期能力2026 年 10 月 4 日状态
1/N运行时 eager EP 扩容已合并于 PR #30164
2/N扩容后的 EPLB已合并于 PR #30553
3/N完整解码 CUDA 图重新捕获已合并于 PR #33723
4/NDP-attention 分片粒度的扩展已合并于 PR #33728
稍后缩容与回增PR #33111 审核中
稍后完全空闲进度计划中
稍后扩容后的恢复计划中

扩容后的 EPLB

扩容提交后,SGLang 在扩展后的拓扑上恢复现有的 EPLB 重新洗牌,使新加入的 rank 能够接收专家。

CUDA 图重新捕获

在 EP4 捕获的图包含依赖拓扑的状态,无法在 EP6 原样重放。最初的扩容路径支持 eager 执行。随着 PR #33723 现已合并,SGLang 还会在提交前为扩展后的拓扑重新捕获完整解码 CUDA 图。预填充和分段重新捕获仍不受支持。

在 256 个 GSM8K 示例和 50 个请求线程的多次重复运行中,扩容后的平均输出吞吐量为:

过渡Eager完整解码 CUDA 图
EP4→EP6371 tok/s1,241 tok/s
EP7→EP8358 tok/s1,120 tok/s

在此设置下,完整解码 CUDA 图的平均输出吞吐量比 eager 执行高 3.1×–3.3×。

多 rank DP-attention 分片

合并后的布局将一个物理 EP rank 映射到一个逻辑 DP worker。后续的 PR #33728 允许一个 DP-attention 副本跨越 attention TP × attention CP 物理 rank,其中 CP 表示上下文并行(Context Parallelism)。在 TP2 和 CP1 下,加入 rank 4–5 会将 DP2/EP4 扩展为 DP3/EP6;加入 rank 6–7 则达到 DP4/EP8。该 API 仍以物理 EP 单位表达目标。

Adding one TP2/CP1 DP-attention shard expands DP2/EP4 to DP3/EP6.

图 4:DP-attention 后续工作将 rank 4–5 作为一个 TP2/CP1 分片接纳,将 DP2/EP4 扩展为 DP3/EP6。

缩容与恢复

后续的 PR #33111 探讨了通过预缩容和退役 rank 状态实现缩容与回增。扩容后的恢复同样必须恢复最后提交的扩展拓扑,而不是启动拓扑。

尝试弹性 EP 扩容

该扩容 API 负责接纳进程;它不分配 GPU。运维人员必须:

  1. 使用 Mooncake、NIXL、初始 EP 大小以及更大的 max_ep_size.

  2. 启动加入的 rank,使用 --elastic-ep-join-mode scale 以及下一个连续 rank 偏移量。

  3. 请求绝对目标并轮询,直到 effective_ep_size 达到该目标。

此示例从 EP4 开始,添加四个 rank 以达到 EP8。有关完整的启动和验证序列,请参阅 扩容测试。以下标志展示了 eager 执行的扩容设置:

primary and joiners:
  --elastic-ep-backend mooncake
  --moe-a2a-backend nixl
  --elastic-ep-initial-size 4
  --max-ep-size 8
  --enable-dp-attention --enable-dp-lm-head
  --deepep-mode low_latency
  --load-balance-method round_robin
  --cuda-graph-backend-decode disabled
  --cuda-graph-backend-prefill disabled

joiners:
  --elastic-ep-join-mode scale
  --elastic-ep-join-rank-offset 4

然后请求并轮询:

curl -X POST http://<PRIMARY_HOST>:21000/scale_elastic_ep \
  -H 'Content-Type: application/json' \
  -d '{"new_ep_size": 8}'

curl http://<PRIMARY_HOST>:21000/is_scaling_elastic_ep

POST 表示已接受,而非已完成。已完成的 EP8 过渡会报告 effective_ep_size: 8, pending_ep_size: null, scale_phase: serving_expanded,且没有错误。

结论

弹性 EP 扩展让 SGLang 最多可添加 GPU rank 至 max_ep_size 而不替换正在运行的部署。它为大型 MoE 模型提供了更细的扩缩单位:只添加下一个拓扑所需的 rank,而现有 rank 在准备期间继续提供服务。

剩余工作遵循相同的协议:准备依赖拓扑的状态,同步每个成员,并且仅在提交后暴露新拓扑。更宽的 DP-attention 布局、缩容、空闲进度以及扩容后的恢复,都建立在已合并的扩容和图重捕获工作之上。

参考文献

致谢

Cheng Wan 和 Shangming Cai 协助完成了上游集成,Xun Sun 构建了本工作所扩展的恢复机制。同时感谢 SGLang、NIXL 和 Mooncake 团队对本次集成的评审与支持。