fix(npu): order SHM H2D with graph replay#2035
Draft
pjgao wants to merge 2 commits into
Draft
Conversation
pjgao
force-pushed
the
bugfix/order-shm-h2d-for-npu-graph
branch
from
July 25, 2026 22:59
8ac687c to
85e3507
Compare
pjgao
force-pushed
the
bugfix/order-shm-h2d-for-npu-graph
branch
from
July 25, 2026 23:35
85e3507 to
4ea2d5c
Compare
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.
背景
PR1964 为减少 Qwen3.5
CausalConv1d前的 Host-to-Device(H2D)空泡,把 SHM 输入的 device materialization 提前到了ForwardSharedMemoryManager::input_read()。在 NPU Graph、schedule overlap、SHM 同时开启时,input_read()运行在后台 polling thread,因此整包 payload 以及linear_state_indices的异步 H2D 都从 polling stream 下发。这条快速路径在普通解码下可以隐藏搬运开销,但 MTP5 会增加 draft、validate 和 Graph replay 轮次,放大 polling stream 与计算线程并发下发的窗口。TP2 两个 rank 的推进顺序一旦不同,一个 rank 可能停在 Graph task update/H2D,另一个 rank 已进入 HCCL 等待,最终表现为不对称等待、卡住或 TPOT 波动。
根因
问题不是 SHM 容量太小,而是 SHM 内存属性和异步执行顺序不成立:
torch::from_blob(..., pinned_memory=true)只修改 Tensor 描述,不能把底层页面变成真正的 pinned memory。linear_state_indices.to(NPU)仍保留了整包 payload 的 polling-stream H2D,虽然能避免卡死,但没有消除共享内存生命周期和跨 stream 排序问题,性能只能到约 2.994 ms TPOT。修改
本 PR 保留 SHM transport、schedule overlap 和 Graph replay,只调整 NPU Graph + overlap 组合下的输入 materialization 位置:
WorkerService在enable_graph && enable_schedule_overlap时调用input_read(..., false),明确禁止 polling thread 发起 NPU H2D。ForwardSharedMemoryManager把本轮 SHM payload 复制到真正的、由ForwardInput持有的 pinned CPU snapshot。这样 producer 可以继续写下一轮 SHM,而当前轮 snapshot 的生命周期覆盖后续异步 H2D。linear_state_indices与整包 payload 一起延迟,不再从 polling stream 单独下发。WorkerImplprepare path,由 ordered prepare stream 执行ForwardInput::to(NPU),再按已有 capture mutex / ready event 顺序进入 Graph task update 和 replay。改动范围为 3 个文件,PR 相对 main 为 41 行新增、13 行删除;没有修改
WorkerImpl的执行逻辑,只复用其已有有序 H2D 路径。跨平台影响被限制在 NPU:
时序图
图中关键术语:
ForwardInput持有,避免 producer 复用 SHM 时破坏尚未完成的 H2D。验证
构建与测试:
xllm目标重新编译、链接成功;BatchTest.SharedMemoryRoundTripPreservesLinearStateIds:PASS;BatchTest.SharedMemoryRoundTripPreservesEmptyRankTensors:PASS;git diff --check:PASS。端到端配置:
log_request数据集,warmup 8,正式 3 × 20,每请求输出 25 tokens;6e2d9a2b对应二进制,正式请求前 ready、真实生成 smoke 均 PASS。最终 60 条结果:
全程无 timeout、无 rank hang;停止后的 PID、端口和 NPU cleanup 为 PASS。作为对照,之前仅延迟
linear_state_indices的窄修复 Client TPOT 为 2.994 ms;本方案恢复到历史 2.9 ms 区间,同时从根因上修复 SHM ownership 与跨 stream 排序问题。本机端到端 binary 同时包含机器所需的权重加载 patch 和 greedy sampling broadcast bypass patch;这两部分不在本 PR 中。