ep: gate intranode worst-token notify host-counter writes for CUDA-graph replay safety - #19
Closed
fergusfinn wants to merge 1 commit into
Closed
ep: gate intranode worst-token notify host-counter writes for CUDA-graph replay safety#19fergusfinn wants to merge 1 commit into
fergusfinn wants to merge 1 commit into
Conversation
…aph replay safety
fergusfinn
pushed a commit
that referenced
this pull request
Jun 25, 2026
…st-token notify host-counter writes
Author
|
Superseded by #18 — the intranode notify gating is folded into the single graph-safe worst-token HT PR (internode + intranode). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makes the DeepEP high-throughput intranode dispatch CUDA-graph replay-safe
when
num_worst_tokens > 0— the single-node analog of the existing internodeworst-token graph-safety. The
num_worst_tokens == 0path is byte-for-byteunchanged.
Problem
intranode::notify_dispatchwrites the host-pinned receive counters(
moe_recv_counter_mapped,moe_recv_expert_counter_mapped) unconditionally.In worst-token mode the host never reads these —
intranode_preparereturnsnum_worst_tokensdirectly — but the kernel still writes them on every call,including CUDA-graph replays, which run with no host pacing.
The host-pinned counter is a single location shared by every dispatch on a
Buffer. When a graph-replayed (worst-token) decode dispatch's counter write
lands mid-flight — after a subsequent host-synced eager dispatch has reset the
counter to −1 but before that eager dispatch's own notify kernel completes — the
eager dispatch's CPU spin-wait observes the stale value and breaks early with a
wrong
num_recv_tokens. Downstream this surfaces non-deterministically as eithera combine-receiver hang (the receiver waits on a tail for tokens that were never
dispatched, then traps) or an illegal memory access once the wrongly-sized
receive buffer feeds the MoE/attention path.
Fix
Thread
num_worst_tokensintointranode::notify_dispatch(kernel, hostwrapper, header, and the
intranode_preparecall site) and gate bothhost-counter writes on
num_worst_tokens == 0, so graph replays never touch thehost-mapped counters and cannot leave a stale value for a later eager dispatch.
Safe because:
num_worst_tokens == 0path;num_recv_tokens = num_worst_tokensandan empty per-expert list, so nothing consumes the gated writes.
Validation
Single 4×GH200 node, DeepSeek-V4-Flash, EP=4,
deepep_high_throughput, fulldecode CUDA graphs. Mixed prefill+decode serving benchmark (random dataset,
ISL/OSL 1024/1024,
--ignore-eos):memory access (surfacing variously at the MoE combine or a downstream GEMM).
~9.5k tok/s sustained, no wedge.