6.4 数据并行与专家并行:横向扩吞吐与 MoE 的 All-to-All
推理 DP 的多副本负载均衡、DP 的两种负载均衡方式、EP 的原理与 EP=TP×DP 的自动计算、EPLB 负载均衡、vLLM 的 EP 配置与依赖
6.1 说”不够快 → DP,MoE 场景 → EP”。这一节把这两个策略讲透。DP 是推理分布式里唯一”几乎零通信”的策略——它靠复制而非切分;EP 则是 MoE 模型(DeepSeek-V3、Mixtral、Qwen3-MoE)的专用策略——它把”专家”当切分单位,用 All-to-All 让 token 找上门。两个策略经常组合使用:EP 负责装下模型,DP 负责扩吞吐。
📑 目录
- 1. 推理数据并行:复制引擎,横向扩吞吐
- 2. DP 的两种负载均衡方式
- 3. DP 的代价与适用边界
- 4. 专家并行:MoE 模型的专用切分
- 5. All-to-All:token 上门的通信原语
- 6. EP 与 TP 的对比:切矩阵 vs 路由
- 7. vLLM 中的 EP:EP=TP×DP 与 EPLB
- 📝 总结
- 🎯 自我检验清单
- 📚 参考资料
1. 推理数据并行:复制引擎,横向扩吞吐
训练 DP 是”每卡一份模型 + 梯度 AllReduce”;推理没有梯度,DP 退化为多份完全独立的模型副本 + 请求分发:
请求流 ──→ [负载均衡器] ──┬──→ 副本 0(完整模型,独立 KV Cache)
├──→ 副本 1(完整模型,独立 KV Cache)
└──→ 副本 2(完整模型,独立 KV Cache)
- 每份副本 = 一个完整模型(权重、KV Cache 全部独立)
- 副本间零通信——没有梯度、没有参数同步
- 副本数 = 吞吐放大的倍数(理想情况线性扩展)
💡 提示:推理 DP 本质就是”多开几个服务实例”。这也是为什么最简单粗暴的 DP 是”跑 N 个独立的 vLLM 进程,前面挂一个 Nginx/负载均衡器”——不需要任何分布式框架。vLLM 内置的 DP 只是把这个模式做进了单进程。
1.1 显存代价
DP 的显存是累加的:DP=4 需要 4 份完整权重。所以 DP 的前提是”单副本装得下”——装不下的模型先 TP/PP/EP 切到单副本能装下,再用 DP 扩吞吐。这也是 vLLM 官方文档强调的组合思路:EP/TP 负责装下,DP 负责吞吐。
2. DP 的两种负载均衡方式
vLLM 的 DP 实现里,请求分发(Load Balancing)有两种模式,对应不同的部署形态:
2.1 内部负载均衡(Hybrid LB)
vLLM 进程内自带的调度器把请求分发给本地的多个 DP rank。适合”单进程多 rank”的部署(一机多卡跑一个 vLLM 实例、DP 组都在本地)。
2.2 外部负载均衡(External LB)
每个 DP rank 独立对外提供 API(--data-parallel-rank 显式指定 rank),外部负载均衡器(Nginx、Kubernetes Service、自研网关)按 rank 分发请求。适合:
- Kubernetes 部署:一个 Pod 一个 rank(one-pod-per-rank),由 K8s Service 做负载均衡
- 多节点部署:每节点一个 vLLM 实例,节点间由外部 LB 分发
2.3 为什么需要关注均衡
DP 的吞吐上限 = 最忙副本的吞吐。负载不均(比如长请求集中在一个副本)会导致:
- 个别副本排队严重(P99 延迟劣化)
- 总吞吐远低于副本数 × 单副本吞吐
📌 关键点:DP 的扩展性 = 负载均衡的质量。vLLM 的默认调度器按请求的预估 token 数做全局均衡,但在线服务里请求长度不可预知,所以生产环境常配合外部 LB + 指标监控(每副本的 queue 长度、GPU 利用率)做动态调整。
3. DP 的代价与适用边界
| 维度 | DP 的代价 |
|---|---|
| 显存 | ×DP(每副本一份完整权重 + KV Cache) |
| 延迟 | 无影响(请求只在单副本内跑,与单卡延迟一致) |
| 通信 | 几乎为零(只有负载均衡的元数据) |
| 利用率 | 低并发时浪费(多副本空闲),高并发时线性扩展 |
适用边界:
- ✅ 单副本装得下、需要横向扩吞吐(最常见)
- ✅ 与 EP 组合:EP 装下 MoE 模型,DP 扩吞吐(6.4 后半)
- ❌ 单副本都装不下(先 TP/PP/EP)
- ❌ 追求单请求最低延迟(DP 不降低延迟,TP 才降)
💡 提示:一个常见误区——“DP 卡越多越快”。DP 只提高并发吞吐,不提高单请求速度。低并发场景加 DP 副本,等于多开几个空转的进程,白白占显存。判断加不加 DP:看 GPU 利用率——如果单副本已经 90%+ 利用率且还有排队请求,加 DP 有效;如果利用率只有 30%,先调并发和 batch,别急着加卡。
4. 专家并行:MoE 模型的专用切分
4.1 MoE 层的结构回顾
MoE 模型的每个 Transformer Block 里,FFN 被替换成多个专家 FFN + 一个路由器:
Attention 输出
│
▼
[Router] ──top-2──→ 每个 token 被分给 2 个专家
├──→ Expert 0 ──┐
├──→ Expert 3 ──┼──→ 加权求和 → 输出
└──→ Expert 7 ──┘
(共 8 个专家,每 token 只激活 2 个)
关键特性:每个 token 只激活全部专家的一小部分(稀疏激活)。DeepSeek-V3 有 256 个专家,每 token 只路由到 8 个。
4.2 不切的问题:显存
如果按 TP 的方式切 MoE,所有专家矩阵都被切开——但 MoE 的”稀疏”特性被破坏了:TP 要求每卡都收到所有 token(数据全量广播),于是每卡都要参与所有专家的计算——稀疏激活的省算力优势荡然无存。而且专家总数 × 单专家大小 = 巨大显存。
EP 的思路完全不同:专家不切,整卡存放。
EP=4(每卡放 2 个专家):
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ Exp 0,1 │ │ Exp 2,3 │ │ Exp 4,5 │ │ Exp 6,7 │
│ +Attn │ │ +Attn │ │ +Attn │ │ +Attn │
└─────────┘ └─────────┘ └─────────┘ └─────────┘
token 想去 Expert 3?→ 通过 All-to-All 发送到卡 1
- 每个专家完整放在一张卡上(不被切开)
- token 在路由时去往专家所在的卡——数据移动代替权重切分
- 每卡只算”自己的专家”,稀疏激活的省算力效果保留(一个 token 只经过 2 张卡)
📌 关键点:EP 的哲学与 TP 相反——TP 是”权重切分、数据广播”(每个 token 经过所有卡、每卡算一部分权重);EP 是”权重整放、数据路由”(每个 token 只经过少数卡、每卡算完整专家)。MoE 的稀疏性决定了:token 只访问少数专家 → 数据路由比权重切分更省通信和算力。
4.3 注意力层怎么办
MoE 模型的 Attention 层仍是稠密的(所有 token 都要),EP 下 Attention 怎么切?vLLM 的规则(6.1 提过):
- TP=1:Attention 权重在所有 DP 副本上复制(纯数据并行)
- TP>1:Attention 按 TP 切分(每个 DP 组内张量并行)
即:EP 只作用于 Expert 层,Attention 层走 TP/DP 自己的逻辑——一个模型里两种并行共存。
5. All-to-All:token 上门的通信原语
EP 的通信发生在路由后:每个 token 要去往的目标专家分布在不同的卡上,需要跨卡搬运 token 的激活。
5.1 All-to-All 语义
All-to-All:每张卡都向其他所有卡发送数据、也从所有卡接收数据(全交换):
卡 0 ──[token 去专家 2,3]──→ 卡 1
卡 0 ←──[token 去专家 0,1]── 卡 1
卡 1 ──[token 去专家 6,7]──→ 卡 3
……(EP 规模内两两互发)
5.2 通信量
EP 层每 token 的通信量 ≈ (要把 token 的激活发给目标专家所在卡),一个 batch 的总量:
对比 TP 的 AllReduce(,且所有卡全收),EP 的通信随”实际路由的 token 数”增长,而不是随全部 batch 增长——负载均衡好时(每个专家收到的 token 数均匀),EP 通信 ≈ TP 通信的 量级。这就是 EP 在超大 MoE 上赢 TP 的根本账。
💡 提示:A2A 的工程优化是 EP 性能的核心战场——DeepEP 库(DeepSeek 开源)专门做 A2A 的 SM 调度优化,vLLM 的
--all2all-backend参数可以选择deepep_high_throughput(prefill 优化)、deepep_low_latency(decode 优化,支持 CUDA Graph)等后端。理解 A2A 是瓶颈后,这些后端选择就顺理成章了。
6. EP 与 TP 的对比:切矩阵 vs 路由
| 维度 | TP(切矩阵) | EP(路由) |
|---|---|---|
| 权重 | 每个矩阵切成 TP 份 | 每个专家整放一张卡 |
| 数据流 | 每 token 广播到所有卡 | 每 token 只发往路由到的卡 |
| 通信原语 | AllReduce(每层 2 次) | All-to-All(每 MoE 层 1 次) |
| 通信量 | (全量) | (按需) |
| 稀疏性 | 被破坏(每卡算所有专家的切片) | 保留(每卡只算自己的专家) |
| 显存 | 线性 ÷TP | 线性 ÷EP(专家数整除) |
| 适合 | 稠密模型 | MoE 模型(专家数多时) |
📌 关键点:EP 不是 TP 的替代,而是 MoE 场景的 TP 替代。稠密模型没有”专家”可路由,EP 无从谈起。而对 DeepSeek-V3(256 专家)这类模型,EP 的优势是决定性的:TP 需要把 256 个专家全部切开广播,EP 只需把 token 发给 8 个目标专家。
7. vLLM 中的 EP:EP=TP×DP 与 EPLB
7.1 配置与自动计算
# 8 卡跑 MoE 模型:TP=2, DP=4 → EP 自动 = 2×4 = 8
vllm serve deepseek-ai/DeepSeek-V3 \
--tensor-parallel-size 2 \
--data-parallel-size 4 \
--enable-expert-parallel \
--max-num-seqs 256
EP_SIZE 的自动计算(vLLM 源码里的核心公式):
- 8 卡全参与专家并行(EP=8):256 个专家 → 每卡 32 个
- Attention 层按 TP=2 切分(4 个 DP 组各自张量并行)
- 不带
--enable-expert-parallel时,MoE 层默认按 TP=TP×DP=8 做张量并行(专家被切开)
7.2 负载均衡:EPLB
EP 的敌人是专家热点——某些专家被大量 token 命中(路由不均),某张卡忙死、其他卡闲死。vLLM 提供 EPLB(Expert Parallelism Load Balancing):
--enable-eplb:启用专家并行负载均衡- 原理:周期性地在 EP 组内迁移热门专家的权重(通过 communicator 在卡间传输专家权重),让每卡负载均衡
- 通信后端:
torch_nccl/torch_gloo/nixl/pynccl
💡 提示:EPLB 的触发条件(窗口内负载不均超过阈值)和迁移策略(
expert_placement_strategy: linear等)都可以配置。生产排错时如果看到”某张卡利用率长期 90%+ 而其他卡 30%“,第一反应就是查路由均衡 + 开 EPLB。
7.3 依赖与前置条件
vLLM 官方文档明确:EP 是实验特性,参数可能变化;且高性能 EP 需要额外安装:
- DeepEP(A2A 通信内核)
- DeepGEMM(MoE GEMM 内核)
- 分离式部署(disaggregated)还需要 gdrcopy
不装这些也能跑(回退到 allgather_reducescatter 通用后端),但性能差一个档次。
📌 关键点:MoE 模型部署的完整配方(vLLM 官方 DeepSeek-V3 部署指南)——EP 装下(—enable-expert-parallel)+ DP 扩吞吐(—data-parallel-size)+ EPLB 均衡热点(—enable-eplb)+ max-num-seqs 调并发。四个参数各管一件事,是理解 MoE 服务化的总纲。
📝 总结
- 推理 DP = 多副本 + 负载均衡:零通信、显存累加,只扩吞吐不降延迟
- 负载均衡是 DP 的生命线:内部 LB(单进程多 rank)与外部 LB(K8s one-pod-per-rank)
- EP 是 MoE 专用策略:专家整放、token 路由(All-to-All),保留稀疏激活优势
- EP 对比 TP:数据路由 vs 权重切分——MoE 越大 EP 越优
- EP=TP×DP 自动计算:Attention 走 TP/DP,Expert 走 EP
- EPLB 治热点:热门专家在卡间迁移,均衡利用率
- 配方:EP + DP + EPLB + max-num-seqs 四件套
🎯 自我检验清单
- 推理 DP 与训练 DP 的本质区别?为什么推理 DP 零通信?
- 为什么说”DP 的扩展性 = 负载均衡的质量”?
- 单副本利用率 30% 时该加 DP 吗?为什么?
- 用”权重切分 vs 数据路由”解释 TP 与 EP 的区别?
- 为什么 TP 会破坏 MoE 的稀疏性而 EP 不会?
- EP=TP×DP 是怎么来的?Attention 层在 EP 下怎么切?
- EP 部署四件套参数分别管什么?
📚 参考资料
- vLLM 官方文档:Data Parallel Deployment(https://docs.vllm.ai/en/latest/serving/data_parallel_deployment/)
- vLLM 官方文档:Expert Parallel Deployment(https://docs.vllm.ai/en/latest/serving/expert_parallel_deployment/)
- vLLM 源码:vllm/config/parallel.py(ParallelConfig,v0.26.0)(https://github.com/vllm-project/vllm/blob/v0.26.0/vllm/config/parallel.py)
- DeepSeek-AI:DeepEP: Efficient Expert Parallelism for Long-Context Models(https://github.com/deepseek-ai/DeepEP)
- Fedus et al., Switch Transformers: Scaling to Trillion Parameter Models(https://arxiv.org/abs/2101.03961)