Elastic Expert Parallelism in vLLM
Elastic Expert Parallelism in vLLM
发表时间: 2026-05 · Blog post by Itay Alroy (NVIDIA), Yongji Wu (Sky Computing), Rui Qiao (Anyscale), Tyler Michael Smith (Red Hat), Moein Khazraee (NVIDIA), Omri Kahalon (NVIDIA), Tzu-Ling Kan (NVIDIA), Ron Tourgeman (NVIDIA) (blog.vllm.ai)
原文: https://blog.vllm.ai/blog/2026-05-14-elastic-expert-parallelism
作者/机构: Itay Alroy (NVIDIA), Yongji Wu (Sky Computing), Rui Qiao (Anyscale), Tyler Michael Smith (Red Hat), Moein Khazraee (NVIDIA), Omri Kahalon (NVIDIA), Tzu-Ling Kan (NVIDIA), Ron Tourgeman (NVIDIA)
速读
一句话结论
vLLM 引入了弹性专家并行(Elastic EP)机制,通过在运行时动态调整数据并行(DP)的 worker 数量来实现混合专家(MoE)模型的无缝扩缩容,从而在不重启服务的情况下应对流量波动并为容错机制提供基础。
要解决什么问题
在混合专家(MoE)模型的推理服务中,为了最大化 KV Cache 容量以支持高并发或超长上下文(如强化学习和多轮 Agent 对话),通常会跨多个 worker 部署专家并行(EP)。然而,在 vLLM 等现有推理框架中,专家并行是完全静态的。一旦部署启动,其服务容量就被固定死。这种静态机制导致了两个严重的卡点:当请求量激增超出当前容量时,系统无法横向扩容来满足需求,只能丢弃大量流量;而当请求量下降时,系统又无法缩容,导致 GPU 资源闲置和成本浪费。过去唯一的解决办法是使用新的配置对整个服务进行完全重启,这个过程非常缓慢且会中断当前的所有服务。要在运行时动态改变 EP 的规模,并非简单地启停进程,因为拓扑结构的改变会直接导致大量运行时状态失效,具体包括:分布式通信组(EP、DP 和全局组绑定了固定的 rank 集合)、专家到 rank 的映射关系、模型权重(新加入的 rank 需要获取权重,现有 rank 需要在重新分配后更新专家权重),以及 CUDA 图捕获和 torch.compile 的编译状态。
怎么做的
核心思路是将扩缩容过程设计为一个与模型前向执行安全共存的协调状态机,通过引入备用通信组和两阶段屏障机制,在后台准备新拓扑状态,最后进行瞬间切换。在 vLLM 中,注意力层在每个数据并行(DP)worker 上独立运行(即 DP Attention),而专家层则在这些 worker 之间共享一个 EP 组,其大小满足公式 $EP = DP \times TP$。弹性 EP 通过单个 API 调用动态改变 DP 的大小,进而触发整个状态机的流转。以从 $DP=N$ 扩容到 $DP=M$ 为例,关键设计由以下几个部件和步骤构成:第一步是触发与请求排空。系统可配置等待飞行中的请求排空(默认超时 120 秒),或立即开始扩容。第二步是新引擎核心初始化。依赖 Ray DP 后端在可用 GPU 上拉起新增的 worker。新 rank 接收当前的专家映射并用占位符初始化模型权重。第三步是建立备用通信组(Standby Groups)。这是最关键的设计之一:系统不会立即销毁当前活跃的通信组,而是利用独立于 PyTorch 全局状态的 StatelessGroupCoordinator,在目标 rank 集合上创建备用组。这使得旧配置在切换前仍能继续执行前向传播。如果使用 NIXL EP 后端,甚至可以通过其 API 增量添加或移除 rank,而不影响现有连接。第四步是专家映射与权重传输。利用备用组广播专家映射,并通过 NVLink 或 RDMA 将非专家权重(注意力层、归一化层、嵌入层等)从现有 rank 均匀传输给新 rank。此时负责专家权重移动的 EPLB(专家并行负载均衡器)会暂停工作。第五步是状态切换。所有 rank 释放 CUDA 图并重置编译状态,将备用组提升为活跃的 EP、DP 和全局组,销毁旧组,重新配置 MoE 模块并重新预热模型。同时在新的 DP 组内同步引擎协调状态(如运行标志、wave 计数器、step 计数器),确保所有 rank 从一致的断点恢复。第六步是 EPLB 重排。新拓扑激活后,EPLB 将专家重新分配到所有 $M$ 个 rank 上,并完成所需的专家权重迁移。如果是缩容,流程基本相同,但 EPLB 重排必须最先执行,以便在移除 rank 前将专家权重合并到存活的 $N$ 个 rank 上。为了协调异步运行的 DP 引擎,防止部分 rank 进入扩缩容阶段而其他 rank 还在执行前向传播导致死锁,系统设计了两阶段屏障:第一阶段带有超时机制,如果超时未完成,先到达的 rank 会推断出有节点进入了下一个引擎步,于是它们也会返回引擎循环再执行一次迭代;直到所有 rank 在同一边界对齐后,再通过无超时的第二阶段屏障共同进入下一阶段。
效果如何
由于本文是一篇工程实现报告,作者并未搭建传统的学术对比实验,也没有提供吞吐量提升等量化指标。实验设置主要基于 DeepSeek-V2-Lite-Chat 这一小型 MoE 模型,在 Ray 集群上进行验证。对比基线即为 vLLM 原有的“静态部署与完全重启”路线。结果表明,通过发送包含目标 DP 数量的 API 请求,系统能够成功在运行时将 DP 规模(例如从 2 扩容到 16,或从 16 缩容到 8),并完成底层拓扑和权重的热切换。这一机制不仅解决了动态伸缩问题,还为 vLLM 的容错服务提供了核心构建块:当检测到节点故障时,可通过先缩容剔除故障节点、再扩容加入替换节点的流程实现恢复。作者也坦诚了当前实现的局限性和代价:目前仅支持张量并行度为 1($TP=1$)、API 服务器数量为 1 的场景;不支持分布式块输出(DBO)或 MoE 投机解码模型;扩缩容操作强依赖 Ray DP 后端。此外,重配置窗口期仍存在一定的性能代价,包括模型重新预热成本和 CUDA 图重新捕获的开销。
主要贡献
在混合专家(MoE)模型的高吞吐量服务中,专家并行(Expert Parallelism, EP)是一项关键技术。广泛的EP部署(即EP跨越多个工作节点)能够最大化键值(KV)缓存容量,从而支持极高的并发量或超长的上下文。这对于需要长上下文和高吞吐量的强化学习工作负载,以及多轮对话会拉长上下文的智能体工作负载尤为重要。
然而,在vLLM及许多其他推理框架中,传统的专家并行是静态的:一旦部署启动,其服务容量便固定不变。如果请求量超过该容量,vLLM无法通过扩容来满足需求;如果需求下降,它也无法缩容以减少GPU使用量和成本。唯一可行的方案是使用新配置进行全面重启,这种方式不仅速度慢,还会导致大量流量丢失。
本文提出了弹性专家并行(Elastic EP),其核心创新点在于允许vLLM在运行时重新配置工作节点(Worker)的数量,使得MoE部署能够根据需求的变化进行动态扩缩容,同时将对服务的干扰降至最低。弹性EP通过增加或移除数据并行(DP)工作节点来实现扩展。在vLLM中,这会改变共享的专家并行(EP)组的大小,并改变专家在工作节点间的分布方式。
该功能的实现使得用户仅需一次API调用即可完成运行时的拓扑重构。例如,以下API调用可将正在运行的部署从当前的DP大小调整为8个工作节点:
curl -X POST http://localhost:8000/scale_elastic_ep \
-H "Content-Type: application/json" \
-d '{"new_data_parallel_size": 8}'
此外,弹性EP不仅支持运行时的动态伸缩(【1,RFC #20323: Elastic Expert Parallelism】),还是vLLM未来实现容错服务(Fault-tolerant serving)的核心构建模块。结合NIXL EP作为通信后端,还可以显著减少扩缩容事件中的重新初始化工作,并提供EP侧的故障检测、报告和恢复能力。
背景知识与设计挑战
在深入探讨弹性扩展机制之前,需要理解弹性EP所依赖的两种并行策略,以及在运行时更改并行度所面临的系统状态挑战。
数据并行(DP)注意力: 该策略利用请求级别的并行性。每个引擎核心(engine-core)处理不同的请求分片(shard),并维护其专属的KV缓存和调度器。这种架构在MLA(Multi-Head Latent Attention)等设计中尤为有用,因为如果使用张量并行(TP),会导致KV缓存跨GPU复制,从而浪费内存并限制批处理大小(【5,RFC #16037: Data Parallel Attention and Expert Parallel MoEs】)。
专家并行(EP): 在MoE模型中,注意力层保持密集计算,而大多数前馈层被替换为稀疏的专家层,将每个Token路由到选定的专家子集。EP不跨GPU对单个专家进行分片,而是将不同的专家分布在不同的GPU上,Token仅被分发到拥有目标专家的GPU上。在vLLM中,注意力机制在每个DP工作节点上独立运行,而专家层则在这些工作节点之间共享一个EP组(EP组的大小为$DP \times TP$)。弹性EP通过在运行时改变DP工作节点的数量,相应地扩展EP组,并在组内重新分配专家。
系统状态改变的挑战: 在运行时扩展DP不仅仅是启动或终止进程那么简单。EP大小的改变会使多个运行时状态失效,具体包括:
- 分布式通信组: EP、DP和全局(World)通信组都嵌入了固定的Rank集合。
- 专家分配: 当EP大小改变时,专家到Rank的映射关系也会随之改变。
- 模型权重: 新加入的Rank需要加载模型权重,而现有的Rank在专家重新分配后可能需要更新其专家权重。
- CUDA图与编译状态: CUDA图(CUDA graphs)的捕获和
torch.compile的编译状态都是基于特定拓扑假设进行特化的,当拓扑改变时,这些假设也会改变。
基于上述挑战,弹性EP的设计原则是将扩缩容视为一个协调状态机(Coordinated state machine)。每个阶段都有明确的同步点,且这些同步点必须与模型的前向执行安全共存。
方法细节
扩容流程(Scale-Up Flow)
从$DP=N$扩容到$DP=M$(其中$M > N$)比缩容更为复杂,因为需要将新的Rank引入到正在运行的部署中。该过程分为以下六个步骤:
1. 触发与请求处理: 扩容操作通过/scale_elastic_ep端点启动。如果系统设置了环境变量VLLM_ELASTIC_EP_DRAIN_REQUESTS=1,vLLM首先会等待处理中的请求排空(Drain),最多等待drain_timeout秒(默认为120秒)。如果没有设置该变量,扩容操作将立即继续进行。
2. 新引擎核心初始化: 启动新的引擎核心工作节点依赖于Ray DP后端。在扩容期间,Ray DP后端会在当前可用的GPU上拉起达到目标DP大小所需的额外DP工作节点。这些新加入的Rank会接收当前的专家映射关系,并使用占位符权重(Placeholder weights)初始化模型。接着,它们会等待后续的传输和重配置阶段,以正式加入活跃拓扑。系统通过两个阶段的信号来协调就绪状态:第一个信号允许现有Rank创建备用通信组;后续的第二个信号则允许开始权重传输。
3. 备用通信组: 这是一个关键的设计选择,vLLM不会立即销毁活跃的通信组。相反,现有的Rank首先会创建覆盖目标Rank集合的备用组(Standby groups)。这些组是通过StatelessGroupCoordinator创建的,它独立于PyTorch的全局WORLD状态。这种设计使得系统能够在切换前准备好新配置,同时旧配置在此期间仍能继续执行前向传递(Forward passes)。如果使用了nixl_ep后端,这种过渡可以是增量的:vLLM无需拆除并重建所有EP侧的连接,而是可以通过NIXL EP的connect_ranks()和disconnect_ranks() API添加或移除Rank,同时保持现有连接不受影响。
4. 专家映射与权重转移: 一旦备用组创建完毕,系统会利用这些备用组广播当前的专家映射,并将非专家权重(如注意力层、归一化层、嵌入层等)从现有的Rank转移到新的Rank。转移工作会尽可能均匀地分配给现有的Rank。弹性EP复用了EPLB(Expert Parallel Load Balancer)用于移动专家权重的GPU到GPU发送/接收路径,但将其扩展到了非专家权重上,利用节点内的NVLink或跨节点的RDMA等高速互连技术进行传输。需要注意的是,专家权重在此阶段不会被移动。它们将在新拓扑激活后,由EPLB在后续阶段进行传输。在过渡期间,普通的EPLB活动会被暂停,以免干扰重配置过程。
5. 切换(The Switch): 切换是所有Rank停止使用旧拓扑并开始使用新拓扑的关键节点。在此阶段,vLLM会严格执行以下步骤:
- 释放CUDA图并重置
torch.compile状态。 - 将备用组提升为活跃的EP、DP和全局通信组。
- 销毁旧的通信组。
- 针对新的EP大小重新配置MoE模块。
- 重新预热(Re-warm)模型,以确保CUDA图和编译路径与新设置相匹配。
在切换过程中,引擎的协调状态(如运行标志位、Wave计数器和Step计数器)会在新的DP组中进行同步,以确保每个Rank都能从一致的断点恢复。此时,新的Rank已经成为活跃DP组的一部分,可以参与前向传递并运行注意力机制,但它们尚未拥有专家。专家的所有权将在随后的EPLB重排中更新。
6. EPLB重排(EPLB Reshuffle): 随着新拓扑的激活,EPLB会在所有$M$个Rank上重新分配专家。这一步会更新专家映射,并执行新布局所需的专家权重移动。在重排完成后,EPLB将恢复正常的运行。
缩容流程(Scale-Down Flow)
从$DP=M$缩容到$DP=N$的过程遵循与扩容相同的总体模式,但存在一个重要的区别:EPLB重排必须首先发生。因为即将被移除的Rank可能仍然拥有专家权重,所以所有的$M$个引擎核心首先参与重排,将专家整合到存活的$N$个Rank上,并将任何必需的专家权重从即将离开的Rank上迁移出去。完成这一步后,系统才会继续执行后续的缩容和移除操作。
跨DP节点的重配置协调
由于DP引擎核心是异步运行的,它们接收到重配置通知的时间可能会有细微差异。当某些Rank进入下一个弹性EP阶段时,其他Rank可能已经开始执行多一个前向步骤。如果提前到达的Rank立即继续执行重配置,整个通信组将在重配置和前向执行之间发生分裂,从而导致部署死锁。
为了解决这个问题,弹性EP采用了一种两阶段屏障(Two-stage barrier)机制:
- 第一阶段屏障(带超时机制): 到达屏障的Rank会等待。如果等待超时,这些Rank会推断出某些对等节点(Peers)已经进入了多一个引擎步骤,因此它们不会单独前进,而是返回引擎循环再执行一次迭代。
- 第二阶段屏障(无超时机制): 在下一次迭代中,一旦所有的Rank都到达了相同的边界,第二个没有超时路径的屏障将允许它们同步进入重配置的下一个阶段。
容错路径(Path to Fault Tolerance)
弹性EP是实现容错服务的核心构建模块,因为它为vLLM提供了故障后所需的运行时重配置路径。如果某个Rank宕机,弹性EP提供了必要的缩容和扩容路径来移除该Rank、重新分配其专家,并在之后无需重启整个部署的情况下将替换容量添加回来(【4,RFC #30112: Fault-Tolerant Expert Parallelism】)。
在宏观层面上,恢复流程包括以下步骤:
- 检测: 通过健康检查或后端特定的故障信号检测到故障。
- 缩容: 执行缩容操作以移除故障的Rank并重新分配其专家。
- 扩容: 一旦有可用的替换容量,再次执行扩容操作。
在此场景中,NIXL EP(【3,PR #35627: [2/N] Elastic EP Milestone 2: Integrating NIXL-EP】)也发挥了重要作用,因为它能够在EP侧检测、报告并从故障中恢复,同时在容量恢复时重新连接替换的Rank。
实验环境与使用指南
该实现目前主要针对Ray DP后端,并要求tensor_parallel_size=1、1个API服务器,且不使用DBO(Dynamic Batch Optimization)。以下是使用DeepSeek-V2-Lite-Chat(作为一个小型MoE模型示例)的具体配置。
启动带有弹性EP的vLLM服务:
vllm serve deepseek-ai/DeepSeek-V2-Lite-Chat \
--trust-remote-code \
--tensor-parallel-size 1 \
--data-parallel-size 2 \
--data-parallel-backend ray \
--api-server-count 1 \
--enable-expert-parallel \
--enable-elastic-ep \
--enable-eplb \
--eplb-config.num_redundant_experts 0 \
--all2all-backend allgather_reducescatter \
--gpu-memory-utilization 0.8
运行时扩容:
使用Ray DP后端时,增加容量可以简单到只需将另一个节点加入Ray集群。一旦Ray识别到新的GPU,弹性EP就可以在运行时将部署扩展到这些GPU上。
例如,在新工作节点上启动Ray:
ray start --address="${HEAD_NODE_IP}:6379"
触发扩容至16个DP:
curl -X POST http://localhost:8000/scale_elastic_ep \
-H "Content-Type: application/json" \
-d '{"new_data_parallel_size": 16}'
运行时缩容:
触发缩容至8个DP:
curl -X POST http://localhost:8000/scale_elastic_ep \
-H "Content-Type: application/json" \
-d '{"new_data_parallel_size": 8}'
使用NIXL EP作为通信后端:
如果希望将NIXL EP与弹性EP结合使用,需安装依赖并在启动时指定后端:
uv pip install nixl
vllm serve deepseek-ai/DeepSeek-V2-Lite-Chat \
--trust-remote-code \
--tensor-parallel-size 1 \
--data-parallel-size 2 \
--data-parallel-backend ray \
--api-server-count 1 \
--enable-expert-parallel \
--enable-elastic-ep \
--enable-eplb \
--all2all-backend nixl_ep
结论与未来展望
弹性EP为vLLM成功引入了核心的运行时重配置路径,使得MoE模型能够根据实时需求动态增减计算资源,避免了高昂的重启开销。尽管当前实现已经具备了核心功能,但其作用域仍然相对特定。作者提出了以下未来工作的方向:
- 支持更丰富的并行配置: 包括支持
tensor_parallel_size>1以及其他额外的并行配置。 - 支持更多服务功能: 目前的实现将
api_server_count限制为1,且尚未支持DBO或MoE的draft/drafter模型。 - 缩减重配置窗口: 在计算重叠(Overlap)、预热成本、CUDA图重新捕获以及复用先前准备好的状态方面,仍有优化空间。
- 将弹性EP与自动缩放策略连接: 目前运行时的控制平面已经就绪,但策略和编排(如Dynamo, llm-d)是独立的后续工作。
- 支持其他DP后端: 目前的扩缩容操作强依赖于Ray DP后端,未来计划扩展至更多后端。
💬 评论讨论
欢迎在这里分享您的想法和见解!