[PR #478] [MERGED] Fix mega_mhc split barriers under CUDA graph replay #478

Closed
opened 2026-10-26 21:18:21 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/deepseek-ai/DeepGEMM/pull/478
Author: @lightseek-bot
Created: 10/19/2026
Status: ✅ Merged
Merged: 10/20/2026
Merged by: @zheanxu

Base: main ← Head: bot/mega-mhc-split-barrier-epoch


📝 Commits (1)

  • dd9cd5f Fix mega_mhc split barriers under CUDA graph replay

📊 Changes

3 files changed (+48 additions, -8 deletions)

View changed files

📝 deep_gemm/include/deep_gemm/impls/sm100_mega_mhc.cuh (+3 -0)
📝 deep_gemm/include/deep_gemm/layout/mega_mhc.cuh (+6 -0)
📝 deep_gemm/include/deep_gemm/scheduler/mega_mhc.cuh (+39 -8)

📄 Description

A CUDA graph kernel node keeps the same %gridid on every replay. The mega_mhc split barriers tag executions with %gridid, so after a replay a barrier line still holds encode_state(grid_idx, kNumSplits) — exactly what the next replay waits for. A Mix or Norm waiter whose m-block init CTA has not started yet proceeds at once and reads the previous replay's split partials (the graph-pool scratch is the same memory). wait_init only protects producers.

This tags each execution with an epoch instead of %gridid. The epoch and an exit count live in the unused tail of the first barrier line, so the host-side barrier buffer and the compiled extension are unchanged (JIT headers only). Every CTA reads the epoch after cudaGridDependencySynchronize(); the last CTA to retire resets the exit count and advances the epoch.

The MegaMoE combine readiness has the same stale-tag problem and is addressed separately in #451.

Validation on B200: one graph node is replayed while alternating two input sets, and every replay is compared bit for bit with eager results (fresh JIT cache per run). Measured on 66081d4, whose versions of these headers differ from main only by an added #include.

case before after
33 tokens, SMs contended by another stream 185/200 wrong 0/400
512 tokens, contended 27/200 0/400
8192 tokens, contended 3/200 0/400
512 tokens, idle GPU 1/200 0/400

Eager calls, and graph replays preceded by an eager launch that rewrites the tag, were 0/200 before the fix as well.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/deepseek-ai/DeepGEMM/pull/478 **Author:** [@lightseek-bot](https://github.com/lightseek-bot) **Created:** 10/19/2026 **Status:** ✅ Merged **Merged:** 10/20/2026 **Merged by:** [@zheanxu](https://github.com/zheanxu) **Base:** `main` ← **Head:** `bot/mega-mhc-split-barrier-epoch` --- ### 📝 Commits (1) - [`dd9cd5f`](https://github.com/deepseek-ai/DeepGEMM/commit/dd9cd5f7064e72c15ff043b4f7ed7b8cc97448cb) Fix mega_mhc split barriers under CUDA graph replay ### 📊 Changes **3 files changed** (+48 additions, -8 deletions) <details> <summary>View changed files</summary> 📝 `deep_gemm/include/deep_gemm/impls/sm100_mega_mhc.cuh` (+3 -0) 📝 `deep_gemm/include/deep_gemm/layout/mega_mhc.cuh` (+6 -0) 📝 `deep_gemm/include/deep_gemm/scheduler/mega_mhc.cuh` (+39 -8) </details> ### 📄 Description A CUDA graph kernel node keeps the same `%gridid` on every replay. The `mega_mhc` split barriers tag executions with `%gridid`, so after a replay a barrier line still holds `encode_state(grid_idx, kNumSplits)` — exactly what the next replay waits for. A Mix or Norm waiter whose m-block init CTA has not started yet proceeds at once and reads the previous replay's split partials (the graph-pool scratch is the same memory). `wait_init` only protects producers. This tags each execution with an epoch instead of `%gridid`. The epoch and an exit count live in the unused tail of the first barrier line, so the host-side barrier buffer and the compiled extension are unchanged (JIT headers only). Every CTA reads the epoch after `cudaGridDependencySynchronize()`; the last CTA to retire resets the exit count and advances the epoch. The MegaMoE combine readiness has the same stale-tag problem and is addressed separately in #451. Validation on B200: one graph node is replayed while alternating two input sets, and every replay is compared bit for bit with eager results (fresh JIT cache per run). Measured on 66081d4, whose versions of these headers differ from `main` only by an added `#include`. | case | before | after | |---|---|---| | 33 tokens, SMs contended by another stream | 185/200 wrong | 0/400 | | 512 tokens, contended | 27/200 | 0/400 | | 8192 tokens, contended | 3/200 | 0/400 | | 512 tokens, idle GPU | 1/200 | 0/400 | Eager calls, and graph replays preceded by an eager launch that rewrites the tag, were 0/200 before the fix as well. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-26 21:18:21 +00:00
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
deepseek-ai/DeepGEMM#478
No description provided.