第16章 DeepEP:MoE all-to-all 通信库

“MoE without efficient all-to-all is just a heavy single-expert model.” —— GShard 团队

V4 把 384 个 expert 跨 8/16/32 卡部署时,每一层都要做一次 all-to-all。DeepEP 让这个原本要 50 ms 的操作压到 0.5 ms。


16.1 引子:MoE 的通信瓶颈

V4 的 MoE 路由产生一个看似无害的需求:每个 token 必须被发到对应 expert 所在的 rank

具体地,在 8 卡 EP 部署中,384 expert 切分成 48 个 / rank。每 token 选 6 个 expert,分布到 8 个 rank 的不同位置。MoE 一层的工作流:

  1. Dispatch:把每个 token 发送到它选中的 6 个 expert 所在的 rank
  2. Compute:每个 rank 计算自己 expert 的输出
  3. Combine:把 expert 输出收回原始 token 所在的 rank(按权重加权求和)

dispatch + combine 都是all-to-all 通信——每个 rank 都要给所有其他 rank 发送 / 接收数据。

如果直接用 NCCL 的 dist.all_to_all

  • 通信量大:每 token 6 × hidden_dim = 6 × 7168 BF16 = 86 KB,1M context 一次 ≈ 90 GB
  • 不规则:每个 rank 接收的 token 数不固定(依赖路由),NCCL 的固定大小 all-to-all 不适合
  • 延迟高:NCCL 的 all-to-all 在小消息上延迟显著(启动 + 同步开销)

DeepEP 是 V4 团队针对 MoE 的 all-to-all 量身定做的通信库——优化了上面三个问题。

flowchart TB
  subgraph 生产部署["384 expert / 8 卡 EP"]
    Token["每 token 选 6 expert"]
    Token --> Disp[Dispatch]
    Disp --> R0[Rank 0: 48 experts]
    Disp --> R1[Rank 1: 48 experts]
    Disp --> Rdot[...]
    Disp --> R7[Rank 7: 48 experts]
    R0 --> Comb[Combine]
    R1 --> Comb
    Rdot --> Comb
    R7 --> Comb
    Comb --> Out[每 token 6 个 expert 输出加权求和]
  end

16.2 DeepEP 仓库结构

DeepEP(github.com/deepseek-ai/DeepEP)的代码组织:

DeepEP/
├── csrc/
│   ├── deep_ep/
│   │   ├── intranode_dispatch.cu      # 节点内 dispatch (NVLink)
│   │   ├── intranode_combine.cu       # 节点内 combine
│   │   ├── internode_dispatch.cu      # 跨节点 dispatch (IB)
│   │   ├── internode_combine.cu       # 跨节点 combine
│   │   ├── low_latency_dispatch.cu    # 低延迟 dispatch (decode 用)
│   │   └── ...
│   └── deep_ep_extension.cpp           # PyTorch binding
├── deep_ep/
│   └── buffer.py                       # Python wrapper
└── tests/

DeepEP 的设计哲学:为不同硬件路径写独立 kernel——节点内(NVLink)走一套、跨节点(IB / RoCE)走另一套,不抽象通用接口。


16.3 dispatch / combine 算法

DeepEP 的核心抽象是 Buffer——预分配的 ring buffer 用于 RDMA / NVLink 传输:

from deep_ep import Buffer

# 创建 buffer
buf = Buffer(group=process_group, num_nvl_bytes=...)

# Dispatch:把 token 按 expert 路由发送到不同 rank
recv_x, recv_topk_idx, recv_topk_weights, ... = buf.dispatch(
    x=token_hidden,                # [B, dim] 当前 rank 的 token hidden
    topk_idx=topk_idx,              # [B, topk] 每 token 的 expert 选择
    topk_weights=topk_weights,      # [B, topk] 路由权重
    num_experts=384,
    ...
)

# 现在每个 rank 收到了"分配给本 rank expert 的所有 token"
# 跑 expert forward
expert_outputs = run_local_experts(recv_x, ...)

# Combine:把 expert 输出收回原始 token 所在 rank
final_outputs = buf.combine(
    x=expert_outputs,
    handle=handle_from_dispatch
)

DeepEP 的 dispatch 算法:

  1. 在每 rank 算”我要发给每个其他 rank 多少 token”——通过 topk_idxexpert_offset_per_rank 计算
  2. 用 NVLink 或 IB 发送 token 数据 + meta-info
  3. 接收端用 ring buffer 暂存
  4. 每 rank 按 expert 顺序排序接收的 token——为后续 grouped GEMM 准备

DeepEP 的 combine 算法是 dispatch 的逆向:

  1. 每 rank 把 expert 输出按”原始 token 所在 rank” 分组
  2. 发送回各 rank
  3. 接收端按原始 token 顺序重组、加权求和

16.3·补 dispatch / combine 双向通信的序列图

把一层 MoE 在 8 卡 EP 部署下的完整通信流画成序列图:

sequenceDiagram
  participant R0 as Rank 0 (expert 0-47)
  participant R1 as Rank 1 (expert 48-95)
  participant Rdot as ...
  participant R7 as Rank 7 (expert 336-383)
  
  Note over R0,R7: 1. Dispatch 阶段 (DeepEP)
  R0->>R1: 发送选了 expert 50 的 token (NVLink)
  R0->>R7: 发送选了 expert 350 的 token
  R1->>R0: 发送选了 expert 5 的 token
  R7->>R0: 发送选了 expert 20 的 token
  Note over R0,R7: 每 rank 收到属于本 rank expert 的 token
  
  Note over R0,R7: 2. Compute 阶段 (DeepGEMM grouped_gemm)
  R0->>R0: 跑 expert 0-47 的 SwiGLU
  R1->>R1: 跑 expert 48-95 的 SwiGLU
  R7->>R7: 跑 expert 336-383 的 SwiGLU
  
  Note over R0,R7: 3. Combine 阶段 (DeepEP)
  R1->>R0: 把 expert 50 输出送回 R0 的原 token
  R7->>R0: 把 expert 350 输出送回
  R0->>R1: 把 expert 5 输出送回
  R0->>R7: 把 expert 20 输出送回
  
  Note over R0,R7: 4. 每 rank 加权求和 + 加 shared expert 输出

dispatch 与 combine 是对称的双向通信——DeepEP 用同一套 Buffer 做这两步,避免重复分配。


16.4 节点内(NVLink)vs 跨节点(IB)路径

DeepEP 区分两条物理通信路径:

节点内 (intranode, NVLink)

  • 同一物理服务器内的 8 卡互联
  • NVLink 带宽 600+ GB/s
  • 延迟 ~1 μs
  • 通信用 GPU 直接 P2P,不经过 CPU / 网卡

跨节点 (internode, InfiniBand / RoCE)

  • 不同物理服务器之间
  • IB / RoCE 带宽 200-400 Gbps(25-50 GB/s)
  • 延迟 ~5-10 μs
  • 通信经过网卡(NIC),可能通过 GPUDirect RDMA 减少 CPU 介入

DeepEP 给两种路径写了完全独立的 kernel——intranode_dispatch.cu vs internode_dispatch.cu。差别极大:

  • intranode:用 NVLink P2P 直接拷贝,不经过 NIC
  • internode:用 RDMA verbs 接口,需要 PD (protection domain)、QP (queue pair) 管理

混合部署(如 16 卡 = 2 × 8 卡 IB 互联)时,DeepEP 会先做节点内 NVLink 通信、再做节点间 IB 通信——避免每个 rank-pair 都用 IB(延迟更高)。


16.5 low-latency dispatch:decode 阶段的特化

V4 的 decode 阶段有特殊需求:每次只 1 token,但通信延迟必须最低(直接影响生成速度)。

DeepEP 提供 low_latency_dispatch

  • 用 GPU-only 实现(不经过 CPU)
  • 用静态 buffer(预分配,避免 malloc)
  • 用单次 RDMA write(不需要 ack),目标 rank 通过 polling 检测新数据
  • 跳过 NCCL 的 collective 同步开销

low-latency 路径在 decode 阶段单层 MoE 的通信耗时约 0.05-0.1 ms,相比 NCCL all-to-all 的 1-2 ms 是 10-20 倍提升。

61 层 × 0.1 ms ≈ 6 ms / token——可以接受。如果用 NCCL,61 × 1.5 ms ≈ 91 ms / token——decode 几乎跑不动。


16.6 DeepEP 的 buffer 与生命周期

DeepEP 的 Buffer 对象在每个进程中是个全局单例——典型生命周期:

# 启动时创建
buf = Buffer(group=ep_group, num_nvl_bytes=2e9, num_rdma_bytes=2e9)
buf.set_num_sms(20)   # 给 dispatch / combine 分配 GPU SM 数

# 每次 forward 调用 dispatch / combine
for layer in transformer.layers:
    h = layer(h)
    if isinstance(layer, MoELayer):
        recv_x, ... = buf.dispatch(x, ...)
        expert_out = run_experts(recv_x)
        combined = buf.combine(expert_out, handle)
        h = combined

# 进程退出时销毁
del buf

num_nvl_bytes / num_rdma_bytes 决定 buffer 容量——必须够大以容纳 prefill 阶段最大单层的所有 dispatch token。如果设小了,dispatch 会失败或回退到慢路径。

set_num_sms(20) 给 DeepEP 分配 20 个 SM 做通信——通常 H100 有 132 个 SM,让 dispatch / combine 与 GEMM 并行。


16.7 与 NCCL all-to-all 的性能对比

把 DeepEP 与 NCCL 的 dist.all_to_all 在 V4 典型 MoE 通信场景下对比(来自 DeepEP README 与公开 benchmark):

场景通信量NCCL all-to-allDeepEP
节点内 8 卡 prefill 1k token86 MB25 ms3 ms
节点内 8 卡 decode 1 token86 KB1.5 ms0.08 ms
跨节点 16 卡 prefill 1k token172 MB50 ms8 ms
跨节点 16 卡 decode 1 token172 KB3 ms0.15 ms

DeepEP 比 NCCL 快约 8-20 倍——主要差距在:

  • low-latency 路径用 polling 而非同步
  • 静态 buffer 避免 malloc
  • 与 grouped GEMM 重叠(DeepEP 的 SM 与 GEMM 的 SM 是分开的)

16.8 集成到 vLLM / SGLang 的工程接缝

把 DeepEP 集成到 vLLM 等推理引擎的工作:

事项 1:替换 MoE 层的通信逻辑

vLLM 的标准 MoE 实现用 torch.distributed.all_to_all。改成 DeepEP 需要:

  • 在 MoE 层前 init Buffer
  • forward 的 all_to_all 调用替换为 buf.dispatch / buf.combine
  • 处理 dispatch 后的 token 重排(DeepEP 输出已按 expert 排序)

事项 2:与 grouped_gemm 配合

DeepEP 的 dispatch 输出格式刚好匹配 DeepGEMM 的 grouped_gemm 输入——两个仓库设计时就考虑了协同。集成时只需要把 dispatch 输出直接传给 grouped_gemm。

事项 3:与 PagedAttention 的并存

PagedAttention 是 attention 的 KV cache 抽象。DeepEP 是 MoE 的通信抽象。两者完全解耦——可以独立集成。但 vLLM 调度器需要识别”MoE 层走 DeepEP,attention 层走 PagedAttention”,分别协调。

事项 4:编译与运行时依赖

DeepEP 需要:

  • CUDA 12.8+
  • libibverbs (跨节点路径)
  • NCCL(用于初始化 process group)
  • ConnectX-7 或更新的 NIC(推荐)

部署到生产时这些依赖必须齐全——这是 V4 跨节点部署的最大工程门槛。


16.9 动手实验:跑 DeepEP intranode benchmark

# 单机 8 卡 H100
git clone https://github.com/deepseek-ai/DeepEP.git
cd DeepEP
pip install -e .

# 跑 intranode dispatch / combine benchmark
torchrun --nproc-per-node=8 tests/test_intranode.py

这个测试会输出每种 dispatch / combine 配置下的吞吐:

  • 不同 token 数(128, 1024, 8192)
  • 不同 expert 数(64, 128, 256, 384)
  • 不同 topk(4, 6, 8)

输出会让你看到 DeepEP 在 H100 NVLink 上的实际 throughput——通常远超 NCCL 的同等场景。


16.9·补 DeepEP 设计的 4 个潜规则

DeepEP 的代码与 NCCL 的设计哲学差异巨大。把 DeepEP 的几个潜规则归纳出来:

潜规则一:用 polling 取代 collective 同步

NCCL 的 collective 操作(all_reduce / all_to_all 等)本质是同步原语——所有 rank 必须到达”通信点”才能开始传输。这个同步点的成本在小消息上极高(~1-2 ms 的 collective 启动延迟)。

DeepEP 的 low-latency 路径用 polling 替代同步:发送方直接 RDMA write 到接收方的预定 buffer 位置;接收方在 GPU 上跑一个 polling loop,检测 buffer 的 magic number 变化。这种”不需要 collective 同步” 的传输让单次通信延迟降到 50-100 μs。

代价是 GPU 的 SM 被占用做 polling——所以 DeepEP 的 set_num_sms(20) 显式分配 20 个 SM 给通信。

潜规则二:静态 buffer 而非动态分配

NCCL 的 all_to_all 每次调用都要 PyTorch 分配 output tensor、计算 metadata、launch kernel。这些 host-side 操作的累积开销在小消息上非常显著。

DeepEP 的 Buffer 一次性预分配几 GB 的 NVL/RDMA 内存——所有后续 dispatch / combine 都在这块预分配空间里跑,不再做任何 host 分配。代价是占用大量显存(典型 2-4 GB),但换来 host-side overhead 接近零。

潜规则三:放弃通用接口,特化 MoE

NCCL 是通用 collective 库——支持各种张量形状、数据类型、reduction op。DeepEP 仅服务 MoE dispatch / combine 这一对操作——但深度优化。

特化的好处:DeepEP 知道每个 rank 持有哪些 expert、知道 token 数量是 batch_size × topk、知道 hidden_dim、知道 dtype。这些”已知约束”让 kernel 可以预先做静态分析、提前 vectorize、提前规划 SMEM。NCCL 这种通用库做不到。

潜规则四:协议简化

NCCL 的传输协议有完整的 ack / retry / 流控机制——保证可靠传输。DeepEP 假设 NVLink / IB 网络已经是”可靠通道”——不做额外 ack。这种”信任底层网络” 的简化让协议头大幅缩减——每条消息几乎只有 hidden 数据本身。

代价是:如果底层网络出错(如 NIC 抖动),DeepEP 不会自动恢复——需要外部检测 + 重启。但生产环境中 IB / NVLink 的可靠性已经极高,这种妥协的成本可控。

这四条潜规则让 DeepEP 不是”通用通信库的更快版”,而是”为 V4 量身定做的特化方案”。如果你的项目不是 MoE,DeepEP 帮不了你——但如果你做 MoE,没有比 DeepEP 更好的选择。


16.9·补·补 DeepEP 与 V4 训练栈的协同

DeepEP 主要在推理 + 训练的 forward 阶段发挥作用——但它在训练 backward 阶段同样关键。

训练 forward:与推理一致,DeepEP 的 dispatch / combine 把 MoE 的通信成本降到最低。

训练 backward:MoE 的反向传播需要把”expert 输出的梯度”反向传回”token 原始位置”——这是 dispatch 的逆向。DeepEP 提供 backward 版本的 dispatch / combine,与 forward 版本对偶。

梯度 all_reduce:MoE 的 expert weight 梯度需要在 EP 维度做 all_reduce(每个 expert 的梯度由所有”看到该 expert”的 rank 累加)。这部分通信用 NCCL 的 all_reduce 而非 DeepEP——因为 expert weight 梯度的形状是固定的,NCCL 已经够好。

优化器状态同步:Muon 的 momentum buffer 在某些训练设置下也需要跨 rank 同步(比如 ZeRO-style 的优化器状态分片)。这部分用 NCCL 的 broadcast / reduce_scatter——不走 DeepEP。

DeepEP + NCCL 在 V4 训练里形成”分工”——前者负责 MoE 的 token 路由通信,后者负责权重 / 状态的同步通信。两者不互相替代。


16.9·延展 DeepEP 在不同硬件配置下的退化路径

DeepEP 假设的最优硬件是”H100/B200 + NVLink + ConnectX-7 IB”——但生产部署可能没这么完美。当硬件配置降级时 DeepEP 的退化路径:

配置 A:H800(H100 中国版)

H800 的 NVLink 带宽被限制(约 400 GB/s vs H100 的 600 GB/s),但 DeepEP 的 intranode kernel 完全兼容。性能退化约 30%——但仍远超 NCCL。

配置 B:A100(无 FP8 / 旧 NVLink)

DeepEP 的 SM90 kernel 不能跑——A100 是 SM80。需要 fallback 到 NCCL all_to_all 或自己写 SM80 版本。V4 在 A100 上的部署方案通常是”放弃 DeepEP、用 NCCL”,性能损失明显但能跑。

配置 C:消费级 GPU(RTX 4090 / 5090)

消费级 GPU 没有 NVLink + 没有 IB,多卡通信只能走 PCIe。DeepEP 在 PCIe 上没有特化路径——性能与 NCCL 接近。这种配置只适合学习 / 个人用,不能跑生产。

配置 D:异构集群(H100 + H800 混合)

DeepEP 不直接支持异构集群——需要把”最弱的硬件”作为基准。生产中应该尽量保持硬件同构。

这些退化路径让 DeepEP 在生产部署时”不挑硬件”——总能跑起来,差异只是性能。但 V4 的设计目标本来就是 H100/B200——其他硬件是”可用但不推荐”。


16.9·延展 DeepEP 与 PyTorch torch.distributed 的关系

DeepEP 不是从零开始的通信库——它建立在 PyTorch torch.distributed 之上:

torch.distributed 提供的基础设施

  • ProcessGroup 抽象(标识”哪些 rank 是一组”)
  • NCCL backend(实际跨 GPU 通信的执行)
  • 各种 collective 原语(all_reduce / all_gather / broadcast 等)
  • 通信器初始化与销毁(init_process_group / destroy_process_group)

DeepEP 在此之上做的事

  • dist.get_world_size() / dist.get_rank() 获取拓扑信息
  • 用 NCCL 来初始化 ProcessGroup(DeepEP 需要这个 group 来知道”在哪些 rank 间通信”)
  • 在 ProcessGroup 之外自己实现dispatch / combine 的快路径(不经过 NCCL)

这种”基础设施依赖 NCCL,性能路径绕开 NCCL”的设计让 DeepEP 与 torch.distributed 共存——你既可以用 DeepEP 跑 V4 MoE,又可以用 NCCL 跑 V4 的 attention all_reduce。

编程模型一致:DeepEP 的 Buffer.dispatch / Buffer.combine 与 dist.all_to_all 的接口风格一致——输入张量、输出张量、可选 metadata。学过 torch.distributed 的工程师能在几小时内理解 DeepEP 的 API。

如果你想深入理解 PyTorch 的 distributed 通信抽象(ProcessGroup、Backend、Work、async_op 等),可以参考《PyTorch 内核源码剖析》中关于 torch.distributed 的章节——那一卷会从 c10d 的 C++ 抽象一路讲到 NCCL backend 的实现。读完那一卷后回来看 DeepEP,会对它的”绕开 NCCL”路径理解更深。


16.9·拓展 DeepEP 在不公开训练栈中的角色

DeepEP 在 V4 inference 路径的角色已经清楚——MoE all-to-all 通信。但 V4 训练时 DeepEP 的角色更复杂——它不只是通信库,还是梯度路由的关键组件

训练时 MoE 每层经历三个通信阶段:

阶段 1:forward dispatch:与推理一样,每 rank 把它的 token 按 expert 分发到对应 rank。

阶段 2:backward 路由梯度:反向传播需要把”expert 输出的梯度” 路由回”token 原始所在 rank”。这是 dispatch 的逆向操作——DeepEP 提供 dispatch_backward / combine_backward 实现。

阶段 3:expert weight 梯度 reduce:每 rank 持有的 expert weight 收到来自多个 token 的梯度——必须做 reduce 累加。这部分用 NCCL all_reduce 而非 DeepEP(因为 weight 形状固定,NCCL 已经够好)。

阶段 1 + 2 用 DeepEP(不规则、按路由动态变化),阶段 3 用 NCCL(规则、固定形状)。这种分工让训练通信成本最优。

梯度路由的复杂度:dispatch 时 token 按 expert id 重排了——backward 时必须按相反顺序重排回去。DeepEP 维护 dispatch 时的 metadata(“哪个 token 去了哪个 rank 的哪个 expert”),让 backward 可以精确逆向。

与 ZeRO 优化器分片的协同:如果 expert weight 用 ZeRO-3 分片(每 rank 持有部分参数),weight 梯度的 all_reduce 还要进一步 reduce_scatter——再多一次通信。DeepEP 不直接支持 ZeRO,但通过预留 hook 让外部框架接入。

理解这些训练通信的复杂度,才能体会到 V4 团队公开 DeepEP 的工程意义——它不只是个推理工具,更是揭示了”如何在 1.6T MoE 上训练 32T tokens”这种规模下通信工程的真实形态。


16.10 延伸阅读

  • DeepEP 仓库 README:本章主要参考
  • NCCL 文档(NVIDIA NCCL):理解 collective 通信的标准实现
  • GShard 论文(arXiv:2006.16668):MoE 的早期 all-to-all 工程
  • ConnectX-7 RDMA 编程指南:理解 IB 通信的硬件细节
  • 本书第 13 章:DeepGEMM 与 DeepEP 的协同
  • 本书第 19 章:vLLM 主仓库 V4 适配 PR 中的 DeepEP 集成

16.10·补 DeepEP 在不同生产场景下的配置建议

部署 V4 时 DeepEP 的几个关键参数需要根据场景调整。给一个配置参考:

场景 1:高吞吐 prefill(长 prompt)

  • num_nvl_bytes:4 GB(容纳大批量 token 一次性 dispatch)
  • num_rdma_bytes:4 GB(跨节点同样需要大 buffer)
  • num_sms:32(给 dispatch 分配更多 SM,减少瓶颈)
  • 不启用 low_latency 路径(prefill 不在意延迟)

场景 2:低延迟 decode(短 prompt)

  • num_nvl_bytes:1 GB(每次 token 量小,buffer 不需要大)
  • num_rdma_bytes:1 GB
  • num_sms:16(给 GEMM 留更多 SM)
  • 启用 low_latency dispatch(关键!延迟敏感)

场景 3:混合工作负载(生产典型)

  • num_nvl_bytes:2 GB(折中)
  • num_rdma_bytes:2 GB
  • num_sms:20-24(折中)
  • 同时启用 normal 和 low_latency 路径——按请求类型 dispatch

场景 4:批量评估(offline batch)

  • num_nvl_bytes:8 GB(极大 batch 场景)
  • num_sms:48(最大化 dispatch / combine 速度)
  • 不启用 low_latency(不在意延迟)

配置错误的影响

  • buffer 设小:dispatch 失败、回退到慢路径,吞吐降 5-10x
  • num_sms 设少:dispatch 成为瓶颈,GEMM 等待
  • num_sms 设多:GEMM 被挤压,整体变慢

调优的方法是按典型 workload 跑 benchmark,找出”DeepEP + GEMM 总时间最短”的配置。这个调优可能要花几天,但一次调好可以用很久。


16.10·补·补 RDMA 通信原语在 DeepEP 中的应用

DeepEP 的跨节点路径用 RDMA verbs 接口——这部分对很多工程师是黑盒。把 DeepEP 用到的关键 RDMA 原语解释清楚:

原语 1:RDMA Write

发送方直接把数据写入接收方的内存——不需要接收方主动 receive。这是 DeepEP 跨节点 dispatch 的基础。

sender:    rdma_post_write(remote_addr, local_buffer, length)
receiver:  poll memory at remote_addr  → 看到新数据后处理

DeepEP 的 internode dispatch 用 RDMA Write 把 token 直接写到目标 rank 的预分配 buffer。

原语 2:RDMA Read

接收方主动从发送方内存读——典型用于”接收方知道发送方已准备好” 的场景。DeepEP 较少用这个。

原语 3:RDMA Atomic

跨节点的原子操作(如 CAS / FAA)。DeepEP 用它做”多个发送方同时往一个 buffer 写时的偏移协调”——避免冲突。

原语 4:Send / Receive (verbs)

带 ack 的可靠传输——比 RDMA Write 慢但更安全。DeepEP 对控制消息(如 metadata 同步)用这个;数据传输用 RDMA Write 跳过 ack。

协议简化

DeepEP 的 low-latency 路径不用 ack——发送方直接 RDMA Write,接收方 polling。这种简化的代价是”不可靠传输”——如果网络出错,DeepEP 不会自动重传。但 IB / RoCE 的硬件可靠性已经极高,这种简化在生产中可接受。

与 PD / QP 的关系

PD(Protection Domain):标识”哪块内存可以被 RDMA”。DeepEP 的 Buffer 在 init 时注册 PD,让其他 rank 可以访问。

QP(Queue Pair):发送 / 接收队列对。每对通信 rank 一个 QP——8 节点意味着 28 个 QP(Cn,2)。DeepEP 在 init 时建立所有 QP,后续通信复用。

理解这些原语让你 debug 跨节点通信问题——常见错误如”PD 创建失败”、“QP 状态错”、“内存未注册” 都能定位到具体步骤。


16.11 本章小结

  • V4 的 MoE 在多卡 / 多节点部署时需要 all-to-all——NCCL 的标准实现远远不够
  • DeepEP 是 V4 团队为 MoE all-to-all 量身定做的通信库
  • 区分 intranode (NVLink) / internode (IB) / low-latency (decode) 三条路径,每条独立 kernel
  • 与 NCCL 比性能差约 8-20 倍——关键在 polling、静态 buffer、与 GEMM 重叠
  • Buffer 对象是核心抽象——预分配 NVL / RDMA 内存
  • 集成到 vLLM 等引擎需要替换 MoE 层的通信、与 grouped_gemm 配合、解决依赖

第 17 章我们离开推理基础设施,进入 V4 的训练栈:Muon 优化器与 32T tokens 的预训练。

评论 0