DeepEP V2.5 Update
先确认版本范围
本文固定 DeepEP 官方 v2.5 分支提交 8c1d13a,并对照 PR #763。截至 2026 年 9 月 25 日,PR 仍处于 open 状态;分支源码的 deep_ep.__version__ 为 2.5.0,但官方 Releases 页面尚无 v2.5 tag。下文的“V2.5”特指这个固定分支,不能当作已合入 main 的稳定版本。版本源码
先记住一个没有改变的主线:MoE 的 dispatch 仍把 token 送到负责相应 expert 的 GPU,combine 再把专家结果送回并汇总;V2.5 的重点是围绕这条主线管理缓冲、专家副本和其他通信,而不是另造一个 token 路由算法。V2.5 README
一个缓冲为什么要拆开
V2 的 ElasticBuffer 同时覆盖 EP、Engram 和 PP。V2.5 将职责拆为四个接口,共享 BufferBase 的运行时生命周期;EP 的 dispatch/combine 仍统一在 EPBuffer 内。这里的“拆”是 API 和资源责任的拆分,不等于四份缓冲必须同时创建。PR #763、BufferBase 源码
| 接口 | 负责的对象 | 主要用途 |
|---|---|---|
EPBuffer |
token、路由元数据、专家副本交换区 | MoE dispatch/combine,以及冗余专家权重与梯度交换 |
EngramBuffer |
分层存放的远端条目 | 从 GPU 或 CPU 存储经 RDMA 取回数据 |
PPBuffer |
相邻流水级的张量槽 | 流水线 send/recv |
BucketBuffer |
一组可共同通信的张量 | CP/DP 的批量 all-gather、reduce-scatter、all-reduce |
四者各有约束。Engram、PP 和 Bucket 在 README 中仍标为 experimental;不能因为它们与 EP 共用基础类,就推断具有相同成熟度。
拆分之后还有一个容易忽略的问题:对称通信缓冲通常要求各 rank 按一致的布局准备存储。新增的 BufferAllocator 先用 meta tensor 记录形状、类型与对齐后的偏移,汇总所需字节数;构造缓冲时,再把这些占位对象变成连续 CUDA 存储上的 view。它使分配计划可在真正占用 GPU 存储前确定。源码没有给出相对 V2 的显存节省比例,不能仅凭“先规划”就声称显存或碎片一定下降。分配器源码、BucketBuffer 构造
热点专家怎样借一张卡
假设 rank 0 的 expert A 在当前批次很忙,框架决定在 rank 1 放一个 A 的副本。要让这个决定真正工作,至少有三件事:把 A 的参数送过去、把一部分 token 改送副本、训练反向时把副本梯度送回原专家。 V2.5 新增的是第一件和第三件的通信原语;副本放在哪里、哪些 token 改道,以及专家 GEMM,仍由上层框架负责。README:Expert load balancing
EPBuffer.lb_prefetch_weights 依据 redundancy_mapping,通过 NVLink 把原专家权重及可选量化 scale 送入副本槽;计算前要等待传输完成。反向阶段,EPBuffer.lb_reduce_grads 按同一映射读取副本的 FP32 梯度,加到原专家已有梯度中。它不会自动清空副本梯度,也不会替框架生成映射。EPBuffer 接口
这个边界影响落地:映射必须在 NVLink 域内各 rank 一致,冗余张量要放在单独预留的负载均衡区域,所有参与 rank 都要调用交换操作。有了权重预取和梯度回累,还不能直接宣称完成了动态负载均衡;收益取决于路由规划、额外存储、预取时机,以及等待最慢 rank 的程度。README:映射与存储约束
EP 之外新增了什么
BucketBuffer 将多张张量放入同一通信存储,提供批量 all-gather、reduce-scatter、all-reduce,覆盖 NVLink、RDMA 和混合域。默认输入应位于 bucket 自己的存储中;普通 PyTorch 张量可用 session() 临时暂存并拷回。这里多了一次 staging 的可能性,因此“支持普通 tensor”不等于零拷贝。当前实现的 all-gather 可由 copy engine 驱动,reduce-scatter 和 all-reduce 仍使用 SM。README:Bucket collectives、session 源码
EngramBuffer 则支持多层条目表,存储可在 GPU 或 CPU;一次 fetch 返回逐层完成 hook,使用某层数据前须等对应 hook。PPBuffer 继续提供相邻流水级之间的发送与接收。这些接口把 DeepEP 的覆盖面扩展到 EP 之外,但官方仍要求把它们视为实验功能。README:Engram 与 PP
EP 本身增加了 延迟收尾:dispatch 或 combine 在 defer_epilogue=True 时先返回事件,调用 .wait() 才在当前流运行对应 epilogue 并取得结果。这样可以把真正独立的计算放在通信与等待之间;若没有独立工作,等待立刻发生,也不会平白获得重叠。展开布局可缓存,专家之间的对齐空隙可清零;清零并不会把尚未接收的容量变成有效 token。README:Deferred epilogues、EPBuffer 源码
迁移时先检查三件事
- 接口与旧依赖。
ElasticBuffer要迁到相应专用 Buffer;V1 API、NVSHMEM 后端和旧文档已从该分支移除。V2.5 的 GPU kernel 改由 DeepJIT 在运行时编译,安装阶段仍会构建 host C++ 扩展。README:更新与安装 - 环境门槛。 分支 README 要求 Linux、Hopper 或更新的 NVIDIA GPU、CUDA Toolkit 13.1+、PyTorch 2.10+、NCCL 2.32.3+、Python 3.10+ 以及支持
std::format的 C++20 编译器;跨机还需 RDMA。安装不要求当时有可见 GPU,运行时 JIT 仍需 CUDA 工具链。README:Requirements - 证据口径。 该分支 README 没有给 V2.5 对 V2 的同条件性能表。V2 README 里的带宽和 SM 数属于旧版本与特定拓扑,不能直接当成这次升级的实测收益。要判断是否值得迁移,应在自己的 EP 规模、batch、top-k、expert skew 和网络拓扑下,分别测 dispatch/combine、端到端 MoE 层,以及新增副本交换或 bucket 暂存的开销。V2 README 固定版本、V2.5 README 固定版本
回到开头的问题:V2.5 最值得关注的是通信职责的重新分界,以及它终于给动态专家副本补齐了权重和梯度两端的交换。 这让上层框架有了更完整的构件,但并没有替它完成负载规划,也还没有公开的 V2.5 对 V2 性能证明。先把 API 与环境迁移跑通,再用自己的路由分布和硬件测量,才知道这半个版本号对实际 MoE 工作负载意味着什么。