跳到主要内容
推理优化

6.4 数据并行与专家并行:横向扩吞吐与 MoE 的 All-to-All

推理 DP 的多副本负载均衡、DP 的两种负载均衡方式、EP 的原理与 EP=TP×DP 的自动计算、EPLB 负载均衡、vLLM 的 EP 配置与依赖

数据并行专家并行MoEAll-to-AllEPLB负载均衡

6.1 说”不够快 → DP,MoE 场景 → EP”。这一节把这两个策略讲透。DP 是推理分布式里唯一”几乎零通信”的策略——它靠复制而非切分;EP 则是 MoE 模型(DeepSeek-V3、Mixtral、Qwen3-MoE)的专用策略——它把”专家”当切分单位,用 All-to-All 让 token 找上门。两个策略经常组合使用:EP 负责装下模型,DP 负责扩吞吐。

📑 目录


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 的通信量 ≈ O(hidden)O(\text{hidden})(要把 token 的激活发给目标专家所在卡),一个 batch 的总量:

A2A 通信量token 数×hidden size×2 bytes\text{A2A 通信量} \approx \text{token 数} \times \text{hidden size} \times 2\text{ bytes}

对比 TP 的 AllReduce(O(hidden×batch)O(\text{hidden} \times \text{batch}),且所有卡全收),EP 的通信随”实际路由的 token 数”增长,而不是随全部 batch 增长——负载均衡好时(每个专家收到的 token 数均匀),EP 通信 ≈ TP 通信的 1/激活专家比例1/\text{激活专家比例} 量级。这就是 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 次)
通信量O(B×H)O(B \times H)(全量)O(路由 token×H)O(\text{路由 token} \times H)(按需)
稀疏性被破坏(每卡算所有专家的切片)保留(每卡只算自己的专家)
显存线性 ÷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 源码里的核心公式):

EP_SIZE=TP_SIZE×DP_SIZE\text{EP\_SIZE} = \text{TP\_SIZE} \times \text{DP\_SIZE}
  • 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 部署四件套参数分别管什么?

📚 参考资料