1. 为什么 MoE 的“先通信后计算”会浪费时间
普通实现会先根据 router 统计每个目的 rank 的 token 数,打包所有 token,完成一次 dispatch all-to-all,待所有 rank 的数据到齐后才启动专家 GEMM;算完再完成一次 combine all-to-all。这种 bulk-synchronous 结构简单,便于验证,却把每一阶段的最长时间全部加在临界路径上。只要网络、计算或尾部 rank 有一个变慢,其他资源就会空转等待。
prefill 批量大,专家 GEMM 较重,网络有机会藏在计算后面;decode 批量小,消息更碎,启动和同步占比会上升。一个静态“通信占比”描述不了这两种负载。需要测的是数据何时抵达、最小可启动计算粒度有多大,以及资源冲突是否允许流水稳定运行。
2. 建立 baseline:先看依赖图,而不是先看 stream 数量
事件图上的箭头都有语义。专家计算要等对应 token payload、索引和 scale 到齐,combine 要等专家结果,输出 scatter 又要等所有 top-k 分支按 gate 合并。overlap 只能调整调度,不能放松这些依赖。先画事件图,后续才能定位等待环和死锁。
3. 细粒度流水:chunk 如何在网络和专家之间流动
把按目的地和专家排好的 token 切成 chunk。chunk 0 到达某个 owner 后无需等待其它 destination 的 payload,立即由该 owner 把它排入专家队列;GPU 同时可继续传 chunk 1,源端也可预打包 chunk 2。计算完成的 chunk 0 立刻进入返回队列,而无需等全部专家完成。理想情况下,流水稳态由三者中最慢的 stage 决定。
公式里没有写元数据和同步开销。chunk 分布不均时,某个专家的大块仍会决定 drain;返回方向饱和时,combine 又会卡住下一批 dispatch 的 buffer reuse。每一级都要有足够且可消化的工作,单纯追求更早启动没有用。
4. Chunk 大小是一个三角权衡
chunk 太大时,早到 token 必须等同目的地的其余 token 才能计算,接近 bulk 行为;chunk 太小时,GPU 需处理大量计数、launch、event 和小消息,GEMM 退化成小矩阵,网络吞吐也达不到有效带宽。第三个维度是失衡:按照固定 token 数切分可能把热点专家的最后一段拖得很长,而按专家边界切分则可能让某些 chunk 极大。
实践中要对 prefill 与 decode 单独设置范围,按 hidden size、top-k、网络拓扑和 GEMM kernel 扫描。不要只观察平均延迟;记录 P99 chunk completion、每个 stage 的空闲比例、每次 launch 的有效 token 数。最佳点一般是一段平台,而不是唯一的神奇数字,调度器应避免在负载轻微变化时频繁跨越该平台边缘。
5. 数据路径之外的元数据往往决定能否启动
对于每个 chunk,owner 至少需要知道 token 的原始位置、选择的专家、gate、payload 长度、量化 scale 和返回目的地。若发送方必须先在 CPU 汇总所有计数,再由 host 发起通信,decode 的小批量会被控制面主导。高性能设计倾向于把计数、prefix-sum、offset 计算、token permutation 和 completion flag 放在 device 端,且让 metadata 与 payload 具有明确的版本和生命周期。
要特别防止 metadata 与 payload 脱节。异步流水中 buffer 很快被下一轮复用;若回收条件只看“通信完成”而没有看“专家读取完成”,下一轮会覆盖仍在 GEMM 中使用的 token。反之,若为安全起见把所有 buffer 都延迟到整层结束才释放,又会把显存和并发限制回 bulk 版本。
6. 正确性协议:每个 token 必须只回来一次、按正确 gate 合并
一个 token 的 top-k 分支可能抵达不同 owner,完成顺序也不同。运行时需要一个可重入的 accumulator:每收到一条返回结果,就按 token id 和 gate 写入或累加;只有所有预期分支完成,token 才可进入下一个层。若使用原子加,必须评估精度和非确定性;若使用分段归约,则要保证分段边界与 route 完全一致。
for returned item (token_id, expert_id, value, gate):
acc[token_id] += gate * value
done[token_id] += 1
if done[token_id] == expected_topk[token_id]:
publish_next_layer(token_id, acc[token_id])
验证不应只比较最终 loss 或文本,因为错位的 token 有时仍会产生看似合理的输出。测试需要构造固定 router、唯一 token id、不同 expert 的可辨识输出,并逐级对比 bulk reference 与 overlap 版本;同时覆盖空专家、重复专家、容量截断、量化、不同 top-k 和跨节点情形。
7. SM、HBM、复制引擎与 NIC 会互相争抢
通信不总是“免费的 DMA”。RDMA 收发、数据 pack/unpack、量化转换、指针和计数处理都可能消耗 GPU SM、HBM 带宽或 NVLink。与此同时 expert GEMM 需要 Tensor Core、shared memory 和 HBM。若把通信 kernel 与 GEMM 强行并发,表面上 timeline 出现重叠,实际上两个 kernel 都变慢,端到端没有收益甚至更差。
应把资源配额纳入设计:不同 stream priority、通信 kernel 可用的 SM 上限、GEMM tile 选择、copy engine 利用率、NIC 亲和性与 HBM 带宽。优化目标是最短 makespan,不是最大的重叠面积。profile 中若看到“overlap 后双方时长同比放大”,说明进入了资源争用区,应缩小通信并发或调整 chunk。
8. 细粒度不等于跨任何网络都有效
节点内 NVLink/NVSwitch 和节点间 RDMA 的启动延迟、带宽、可并发队列和拥塞模式不同。极细的 chunk 在高延迟链路上容易退化为大量小包;不对称 NIC 映射会使某些 owner 早到、某些 owner长期拖尾。一个局部数据中心拓扑优化也可能在多节点 EP group 中失效。
部署时先固定 rank-to-GPU-to-NIC 映射,做方向性的 all-to-all microbenchmark,再运行真实 router trace。网络测量要包含同时存在 TP collective、KV transfer 或其他租户流量的干扰条件。只有单独链路满带宽,不代表在完整 serving graph 中还能重叠。
9. 运行时调度器要管理“未完成工作”,而不只是 batch
bulk 模式中,一层结束是天然 barrier;细粒度模式下,系统同时有正在 pack、在网、等待专家、正在计算、等待返回和已可进入下一层的 token。调度器需要 backpressure:当某个 owner 或返回队列积压时,限制新 chunk 注入;当 KV 或 buffer 临近上限时,优先完成已在途工作而不是继续接纳新的 prefill。
一个实用模型是维护每个 stage 的队列长度和预测服务时间,用水位而非单点瞬时值决定是否发下一批。水位太低会断流,太高会增加显存和等待。特别是在 decode 中,单用户 token 的 deadline 很短,不能因为 prefill 流量可产生更大 chunk 就长期抢占专家或网络。
10. 调参实验应以反证为导向
先建立无 overlap 的正确基线,固定模型、route trace、精度和硬件。一次只扫一个维度:chunk token 数、chunk 数量上限、通信 stream 数、通信 SM 配额、GEMM tile、EP group 大小。每个点记录端到端 layer time、stage 空闲、通信和计算的单独时长、P99 chunk 完成以及数值差异。
要设计能推翻假设的实验。例如认为“网络慢”时,关闭专家 GEMM 或替换为轻量 kernel,看 dispatch 是否仍是主导;认为“chunk 过大”时,减半并观察 warmup、launch 和有效 GEMM 大小;认为“重叠不够”时,测资源争用后是否反而变慢。没有这些对照,漂亮的时间线很容易是偶然的 batch shape。
11. 失效模式:重叠为何常常没有兑现
12. 生产可观测性:给每一个阶段留证据
至少记录 chunk 的创建、发送、到达、专家开始、专家结束、返回和释放事件,并以 request/batch/layer/chunk/rank 关联。将这些事件采样而非全量持久化,避免观测本身干扰调度。仪表盘应能展示:每个 stage 的队列水位、最慢 rank、最大 expert load、通信与计算重叠比、P99 drain、错误重试和 buffer pool 高水位。
报警不要只基于平均 GPU util。更有价值的是在固定流量下,P99 token latency 增大且某个 rank 的 recv/send 比失衡,或 buffer pool 连续多个窗口接近耗尽。这样运维才能判断是模型 route 漂移、集群拓扑问题、通信库回归还是调度器策略造成。
13. 与其他 Mainline 主题的关系
本页的 overlap 发生在 EP 与 DeepEP 的 dispatch/combine 图中。它需要 GPU 算子 中的 stream、事件和带宽意识,受 通信拓扑 限制,并最终由 运行时调度器 决定如何与 prefill、decode 和 KV 资源共存。它不是孤立的 kernel 技巧。
14. 资料与边界
| 来源 | 用途 |
|---|---|
| DeepEP 官方仓库 | MoE dispatch/combine 实现与版本化资料入口。 |
| NCCL 官方文档 | collective、stream 与通信语义的基础资料。 |
| Mainline:MoE | 路由、专家和模型级成本的独立解释。 |
题目中的名称用于定位阅读材料。本文不会据此断言某一实现的专有设计或性能结论;遇到具体项目时,应以其公开论文、代码和实验配置为最终证据。