[Bugfix] Reset MegaMoE combine readiness for CUDA graph replay - #451
foreverrookie wants to merge 2 commits into
Conversation
CUDA graph replay can reuse the kernel grid ID. Clear local peer-ready flags before the existing pull barrier so a later replay cannot consume the previous invocation's combine data when inputs change. Preserve the workspace layout and existing barriers. Validated on 8 B300 ranks with input staging, unequal/empty source ranks, and successive CUDA graph replays with updated inputs (3 tests passed per rank). Co-authored-by: Codex <noreply@openai.com> Signed-off-by: foreverrookie <49910994+foreverrookie@users.noreply.github.com>
| @@ -388,10 +388,13 @@ sm100_fp8_fp4_mega_moe_impl(void* y, | |||
|
|
|||
| // Write expert count | |||
| if (sm_idx == 0) { | |||
There was a problem hiding this comment.
🔵 suggestion: combine readiness 的推送、清零、notify、等待逻辑在 bf16 与 fp8_fp4 两个 impl 中逐行重复,本次修复恰好只落在其中一个文件,说明重复代码已造成一致性问题。可选的后续改进:将 “push peer grid idx + reset local readiness” 与 “notify/wait” 抽成 comm/ 或 layout/ 下的小工具函数(例如 MegaMoEWorkspace 上的成员),两个 kernel 共用,避免后续修复再次只覆盖一处。
🤖 v5
🤖 ds-review-bot Code Reviewv6未发现本次变更新引入的缺陷。FP8/FP4 路径在现有 pull barrier 前重置本地 readiness,能够隔离旧标记与当前调用的完成通知,且未改变工作区布局。当前环境缺少 CUDA 工具和 GPU,未运行多卡回归测试。 v5本次修复在 sm100_fp8_fp4_mega_moe.cuh 的 dispatch 阶段(SM 0、pull barrier 之前)将本 rank 的 combine_ready_grid_idx[peer] 清零,并同步更新了 layout/mega_moe.cuh 中的注释。修复思路正确,已验证:(1) 清零位于 kBeforeDispatchPullBarrierTag NVLink barrier 之前,peer 本轮的 st_rel_sys notify 只能在其通过该 barrier 之后(依赖本 rank 已完成清零)发出,不会被清零覆盖;(2) 上一轮的 notify 由 kDispatchWithEpilogueBarrierIdx 同步排在 kAfterWorkspaceCleanBarrierTag 之前,在下一次 launch 开始前已全部落地,不会晚于本轮清零到达;(3) 本 rank epilogue 的 wait 位于 epilogue grid sync 与 kDispatchWithEpilogueBarrierIdx 之后,严格晚于 SM 0 dispatch 的清零;(4) 重置值 0 与 grid_idx + 1 (>= 1) 不冲突,workspace 布局(MegaMoESignals 偏移 128 的 static_assert)与现有 barrier 均未改动;(5) layout/mega_moe.cuh 注释准确描述了 FP8/FP4 路径的新语义。但修复不完整:sm100_bf16_mega_moe.cuh 使用完全相同的 peer_grid_idx 推送 / st_rel_sys notify / ld_acq_sys == grid_idx 等待协议,却没有加入同样的清零,在 CUDA graph replay 复用 %gridid 时仍会读到过期或部分更新的 combine 结果。 v4The FP8/FP4 part of this change is correct. Clearing each rank's local Files reviewed: 2 📍 未定位到 diff 的评论🔴 critical 建议在 sm100_bf16_mega_moe.cuh 的 if (thread_idx < kNumRanks) {
ptx::st_rel_sys(workspace.get_combine_ready_grid_idx_ptr(thread_idx), uint64_t(0));
*sym_buffer.map(workspace.get_peer_grid_idx_ptr(sym_buffer.rank_idx), thread_idx) = ptx::get_grid_idx() + 1;
}并同步更新注释;同时将 BF16 路径也纳入 CUDA graph replay 回归测试(同一 graph、更新输入后连续 replay)。 🤖 v5 🟡 warning |
Reset peer-ready flags before the existing pull barrier, matching the FP8/FP4 path and preventing stale completion tags on graph replay. Co-authored-by: OpenAI Codex <noreply@openai.com> Signed-off-by: foreverrookie <49910994+foreverrookie@users.noreply.github.com>
|
Added the same BF16 reset in 7e924a8. On 2 B300 GPUs, changed-input graph replay failed before the fix in balanced, unequal, and empty-source cases; after the fix, all 12 replays per case match eager output exactly. |
CUDA graph replay can reuse
%gridid, allowing MegaMoE to accept stale combine-readiness tags and read old or partially updated results.Reset local peer-readiness flags before the existing pull barrier in both FP8/FP4 and BF16 kernels. The workspace layout and existing barriers are unchanged.
Validation:
AI assistance was used for the fix and validation.