Skip to content

fix(deepseek-v4): route large-token fused mHC around the allinone cliff#622

Draft
Xiangyi1996 wants to merge 1 commit into
perf/v4-trtllm-mhc-decode-gatingfrom
xiangyi/v4-mhc-cliff-routing
Draft

fix(deepseek-v4): route large-token fused mHC around the allinone cliff#622
Xiangyi1996 wants to merge 1 commit into
perf/v4-trtllm-mhc-decode-gatingfrom
xiangyi/v4-mhc-cliff-routing

Conversation

@Xiangyi1996

@Xiangyi1996 Xiangyi1996 commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

Stacked on #600. Routes fused-mHC calls with more than 32 tokens through the composed two-stage path (post_mapping + prenorm split-K GEMM + big fuse) instead of the vendored allinone kernel, with once-per-shape selection logging. B <= 32 keeps the current allinone path, so the canonical p8 (verify M=32) path is unchanged in compute and kernel behavior (the change adds a once-per-shape selection log and a small process-global logging set).

Why

Above 32 tokens the allinone entry dispatches to a tf32 atomic variant with a ~10x per-call cliff (kernel identity confirmed via profiler):

M allinone (us/call) composed (us/call)
16 16.0 21.4
32 22.1 21.3
36 222.5 22.9
40-128 222-242 21.4-24.6

Any decode step with bs >= 9 at verify width 4 (M >= 36), p16-class workloads, or a wider verify would hit ~122 calls x ~230us = ~28 ms/step. This PR claims cliff avoidance only — no canonical p8 speedup is claimed.

Evidence

  • Single-call CUDA-graph replay microbench (B200), cliff onset at M=36; measurement-artifact cross-check with 20-call graphs.
  • Numeric parity: all four outputs (residual, layer_input, post, comb) within 1.2% relative error over 8 chained layers at M in {16,32,36,40,64}.
  • Routing tests: threshold boundary, allinone preserved at/below threshold, empty batch, once-per-shape logging.

CI notes

  • Both test files are registered for the runtime-1gpu suite; the GPU parity file is restricted to B200-class runners (TRT-LLM mHC kernels are sm100-only) with a runtime sm100 skip as well.
  • CUDA-graph capture/replay of the composed path at M in {36,64} is covered (replay stability, static-input mutation, no graph-pool growth over 50 replays).
  • Base is fix(deepseek-v4): gate experimental TRT-LLM mHC backend #600 (not main), so GPU Actions do not auto-run here; evidence is from manual B200 runs (21/21). A formal CI pass is required after fix(deepseek-v4): gate experimental TRT-LLM mHC backend #600 lands and this retargets main.

GPU closure evidence (added)

  • Numeric parity (GPU): 21/21 — true allinone-vs-composed 8-layer chained parity at M in {16,32} x 3 seeds AND at the affected shapes M in {36,40,64} x 2 seeds (allinone forced above the routing threshold), with bf16 depth-scaled ULP bounds, separate fp32 bounds for post/comb, and 3% relative error; the routed wrapper output additionally equals the composed reference exactly at M in {36,40,64}.
  • Graph memory: a 122-call captured graph of the composed path reserves ~25 MB, same as allinone; per-call temporaries are recycled inside the capture pool (no per-layer accumulation, no p16 OOM risk).
  • Forced M>32 end-to-end (p12/n24, TP8 integration stack): 276/276; runtime selection logs show M=48..96 on the composed path and draft M=8..12 on allinone. Single-change attribution arm (canonical + this patch only) vs canonical control, same node/protocol back-to-back:
p12 canonical this patch delta
TPOT 31.84 ms 20.14 ms -36.7%
steady completion tok/s 397.9 626.7 +57.5%
MTP acceptance 0.6688 0.6685 matched
cache hit 90.91% 90.91% matched

The p12 shape (verify M=48) hits the allinone tf32-atomic cliff on every decode step in the control arm; this is the end-to-end realization of the microbenched ~10x per-call cliff. Canonical p8 (M=32) remains on the unchanged allinone path.

@Xiangyi1996 Xiangyi1996 force-pushed the xiangyi/v4-mhc-cliff-routing branch 6 times, most recently from 45a8f32 to 4ff0cf6 Compare July 10, 2026 03:48
The vendored allinone kernel dispatches to a tf32 atomic variant above 32
tokens that runs ~10x slower per call (222-240us vs a flat ~23us for the
composed post_mapping + prenorm-GEMM + big-fuse path; kernel identity
confirmed via profiler, outputs agree within 1.2% relative error over 8
chained layers on all four outputs). Route B>32 through the composed path,
keep allinone at B<=32 so the canonical p8 (M=32) path is unchanged, and log
each (num_tokens, path) selection once per process.

Signed-off-by: Xiangyi Zhang <xiangyiz@nvidia.com>
@Xiangyi1996 Xiangyi1996 force-pushed the xiangyi/v4-mhc-cliff-routing branch from 4ff0cf6 to 271bd32 Compare July 10, 2026 04:47
@Xiangyi1996 Xiangyi1996 marked this pull request as ready for review July 10, 2026 05:09
@Xiangyi1996 Xiangyi1996 requested a review from a team as a code owner July 10, 2026 05:09

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 271bd32b8b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +642 to +643
residual_cur = _trtllm_mhc_post(x_prev, residual_prev, post_prev, comb_prev)
layer_input, post_cur, comb_cur = _trtllm_mhc_pre(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve allinone when DeepGEMM is unavailable

When TOKENSPEED_V4_MHC_BACKEND=trtllm runs on an SM100 host with the TRT-LLM mHC kernels installed but without the optional DeepGEMM mHC op, any fused call with more than 32 flattened tokens now enters this composed branch and then _trtllm_mhc_pre unconditionally calls deep_gemm_mhc_prenorm_gemm. _use_trtllm_mhc only checked supports_trtllm_mhc, so in that supported TRT-LLM-only install the DeepGEMM symbol is still error_fn and these calls raise RuntimeError("Kernel implementation not found"), whereas they previously ran through the allinone kernel. Gate this reroute on has_deep_gemm_mhc() or fall back to allinone when DeepGEMM is absent.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant