Skip to content

[None][feat] DeepSeek V4 / DSpark optimizations on Rubin - #19961

Merged
reasonsolo merged 19 commits into
NVIDIA:mainfrom
reasonsolo:user/lizhiz/rubin-mb4-pr3-dsv4
Oct 24, 2026
Merged

reasonsolo merged 19 commits into
NVIDIA:mainfrom
reasonsolo:user/lizhiz/rubin-mb4-pr3-dsv4

Conversation

@reasonsolo

@reasonsolo reasonsolo commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

Dev Engineer Review

The current diff only reformats imports in cute_dsl_custom_ops.py, accuracy_core.py, and test_fp8_block_scale_gemm.py. It does not change runtime behavior, APIs, test logic, or test-list configuration. Review finding counts and test results are unavailable.

QA Engineer Review

One test file changed. Its edits only reformat imports; test functions, selectors, and test-list entries are unchanged. No integration test-list update applies. Coverage verdict: sufficient for the formatting-only diff. Test execution is not established.

Per-File QA Perspective

  • tensorrt_llm/_torch/custom_ops/cute_dsl_custom_ops.py: Import formatting only. No observable behavior change requires QA verification.
  • tests/integration/defs/accuracy/accuracy_core.py: Import formatting only. No evaluator behavior change requires QA verification.
  • tests/unittest/_torch/thop/parallel/test_fp8_block_scale_gemm.py: Import formatting only. Existing FP8 GEMM and DSv4 fusion tests are unchanged; the file has no integration test-list entry.

Description

This PR completes the DeepSeek V4 fast paths on Rubin (SM107) whose kernels and ops are already in main but
not wired in. It also adds the DSpark accuracy coverage used to validate them.

q_b GEMM + RMSNorm + RoPE fusion. On SM107, with FP8 block-scaled q_b_proj on the CuTe DSL path, the
DeepSeek V4 MLA module now calls cute_dsl_dsv4_qb_gemm_fused_rmsnorm_rope_quant.

  • It covers decode only, by design: DeepSeek V4 attention metadata does not set cu_q_seqlens, so context
    and mixed batches take the unfused path.
  • The kernel writes the complete rotated FP8 Q, so the generation path runs only the KV half of
    mla_rope_generation (q_rope_applied). The context-side plumbing (the thop sparse-MLA context branch
    accepting no q_pe when quant_q_buffer already holds rotated Q) is in place for a later prefill path
    but is not exercised yet.
  • The prologue issues kv_a_proj before the aux-stream compressor and indexer prework, which share one start
    event.
  • The fusion op is autotuned over 1-CTA and 2-CTA cluster tactics.
  • Disable with TRTLLM_DISABLE_DSV4_Q_B_GEMM_NORM_ROPE_FUSION=1.

Direct-output o_b projection. With the fused attention epilogue, both O-LoRA projections run inside the
MLA custom op and write the hidden states into its single mutable output, as the attention developer guide
describes.

  • On SM107, o_a_proj emits FP8 O-LoRA with packed UE8M0 scales, and o_b_proj runs as an MXFP8 GEMM straight
    into the output (new cute_dsl_mxfp8_gemm_inplace_rubin).
  • Other SM100-family GPUs copy the o_b_proj result into the output's leading columns.

Tests.

  • Unit:
    • test_deepseek_v4_q_b_fusion.py.
    • Extended test_mla_registry.py.
    • SM107 op tests for the autotuned q_b fusion and the in-place MXFP8 GEMM.
  • Integration:
    • TestDeepSeekV4ProDSpark::test_gsm8k_dep4_megamoe_cutedsl: NVFP4 export, MegaMoE CuTe DSL, DEP4,
      GSM8K + acceptance length. Runs on l0_gb300_multi_gpus.
    • TestDeepSeekV4ProDSparkMultinode::test_gsm8k_1p1d_dep4: two-node 1P1D disaggregated GSM8K. QA
      multi-node list, because it needs one pytest task per node.
    • Reference rows for both.

SM107 fixes.

  • DeepSeek V4 now defaults use_cute_dsl_blockscaling_mm to on for SM107, so its FP8 block-scale linears take the CuTe DSL GEMM path.
  • DeepGEMM JIT kernels are built as sm_100f on SM107 again (new 3rdparty/patches/deepgemm_sm107_arch_family.patch). After the DeepGEMM bump, they were built as sm_107f. The bundled CUTLASS has no SM107 target, so the TMA descriptor prefetch hit a device assert, for example in the DSA indexer's fp8_paged_mqa_logits.

DFlash dummy slot. CUDA-graph padding and attention-DP dummy requests share the DFlash worker's dummy slot,
which is never freed. Main now keeps that slot's drafter context empty (_advance_ctx_len, #19988); this PR adds
a regression test that drives the drafter-input step over a real slot and a padding row.

Not included. Block-scaled FP8 projections for DSpark: main does not run the DSpark CuTe DSL kernels on
SM107 yet, so that work needs a separate enablement PR first. The SM107 block-scale default above covers the DeepSeek V4 main model only.

Test Coverage

  • tests/unittest/_torch/attention/sparse/deepseek_v4/test_deepseek_v4_q_b_fusion.py
  • tests/unittest/_torch/attention/test_mla_registry.py
  • tests/unittest/_torch/thop/parallel/test_fp8_block_scale_gemm.py (SM107)
  • tests/unittest/_torch/modeling/test_modeling_deepseekv4.py (model defaults, including SM107)
  • tests/unittest/_torch/speculative/hw_agnostic/test_dflash_worker.py::test_generation_step_keeps_the_dummy_slot_context_empty
  • tests/unittest/disaggregated/test_cache_reuse_adapter.py::TestCreateKvSliceBlockSpan::test_dspark_gen_init_draft_reserve_block_is_trimmed
  • accuracy/test_llm_api_pytorch.py::TestDeepSeekV4ProDSpark::test_gsm8k_dep4_megamoe_cutedsl
  • accuracy/test_disaggregated_multinode.py::TestDeepSeekV4ProDSparkMultinode::test_gsm8k_1p1d_dep4

PR Checklist

Please review the following before submitting your PR:

  • PR description clearly explains what and why. If using CodeRabbit's summary, please make sure it makes sense.

  • PR Follows TRT-LLM CODING GUIDELINES to the best of your knowledge.

  • Test cases are provided for new code paths (see test instructions)

  • If PR introduces API changes, an appropriate PR label is added - either api-compatible or api-breaking. For api-breaking, include BREAKING in the PR title.

  • Any new dependencies have been scanned for license and vulnerabilities

  • CODEOWNERS updated if ownership changes

  • Documentation updated as needed

  • Update tava architecture diagram if there is a significant design change in PR.

  • The reviewers assigned automatically/manually are appropriate for the PR.

  • Please check this after reviewing the above items as appropriate for this PR.

GitHub Bot Help

To see a list of available CI bot commands, please comment /bot help.

@reasonsolo
reasonsolo force-pushed the user/lizhiz/rubin-mb4-pr3-dsv4 branch 2 times, most recently from 0f66060 to 7cfa431 Compare October 8, 2026 07:56
@reasonsolo
reasonsolo force-pushed the user/lizhiz/rubin-mb4-pr3-dsv4 branch 2 times, most recently from e2696e8 to a9426df Compare October 9, 2026 06:53

@Barry-Delaney Barry-Delaney left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed the code at a9426df, including the changes relative to the shared merge-back prerequisite. The SM107 Q-projection fusion gates and fallback paths, mixed context/generation handling, single mutable MLA output contract, non-aliasing O-LoRA scratch, Blackwell output consumers, and DFlash dummy-slot reset look sound. No blocking code findings.

Validation: source and call-path review; all 12 changed Python files parse and git diff --check passes. GPU execution was not performed locally; accepting the author-reported functional results. This is a code approval; CI and draft readiness remain with the author.

@reasonsolo
reasonsolo force-pushed the user/lizhiz/rubin-mb4-pr3-dsv4 branch 2 times, most recently from 1a7be57 to 39a3e84 Compare October 15, 2026 07:13
@reasonsolo

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #78047 [ run ] triggered by Bot. Commit: 39a3e84 Link to invocation

@reasonsolo reasonsolo added the api-compatible Accepted LLM API contract change that is backwards-compatible label Oct 15, 2026
@reasonsolo
reasonsolo force-pushed the user/lizhiz/rubin-mb4-pr3-dsv4 branch from 39a3e84 to 296540e Compare October 15, 2026 08:03
@reasonsolo

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@reasonsolo
reasonsolo marked this pull request as ready for review October 15, 2026 08:06
@reasonsolo
reasonsolo requested review from a team as code owners October 15, 2026 08:06
reasonsolo and others added 15 commits October 24, 2026 02:37
CUDA-graph padding and attention-DP dummy requests all map to the DFlash
worker's dummy slot, which no request ever frees. If the generation step
advanced that slot's context length like a real slot's, the dummies'
drafter context would grow every step up to the context cap. Main zeroes
it after each update (DFlashWorker._advance_ctx_len, NVIDIA#19988).

Add a regression test that drives prepare_1st_drafter_inputs over a real
slot and a padding row and checks that only the real slot advances.

Signed-off-by: Lizhi Zhou <1432185+reasonsolo@users.noreply.github.com>
… kv-norm

The q_b GEMM + RMSNorm + RoPE fusion writes the complete rotated Q, so the
generation half runs mla_rope_generation with kv_only=True. kv_only needs
kv_norm_weight, which is only passed when _fused_kv_norm_active is set; the
q_b gate did not check that flag, so a generation batch where the fused
kv-norm prologue is off (for example when _fused_q_rope_specs cannot build a
spec) would trip "kv_only requires kv_norm_weight" in the op.

Require _fused_kv_norm_active before taking the q_b fusion, matching the
"both or neither" coupling the fused prologue already enforces.

Signed-off-by: Lizhi Zhou <1432185+reasonsolo@users.noreply.github.com>
…onfig contexts

Runner applied ModelLoader.load_config_and_apply_defaults before entering
scaled_from_ctx and vision_config_ctx, so with vision_config="none" the
defaults were resolved from the composite checkpoint config (and its
*ForConditionalGeneration class) while the model itself loads from the
text-only config. Resolve the defaults and build the ModelLoader inside the
same contexts that model_loader.load() runs under.

Add a CPU unit test that stubs ModelLoader and checks the llm_args it
receives: parallelism derived from a multi-rank mapping, a model default
applied, and the defaults resolved through the text-only config loader.

Signed-off-by: Lizhi Zhou <1432185+reasonsolo@users.noreply.github.com>
…match

AccuracyTask.evaluate() used a caller-supplied prepared_evaluator as is.
In INTEGRATION_TEST mode the hypothesis test switches to one sample, but a
full-size prepared evaluator would still run every sample. Raise a
ValueError when the prepared evaluator's num_samples differs from the
sample count of this evaluation.

Signed-off-by: Lizhi Zhou <1432185+reasonsolo@users.noreply.github.com>
…uest timeout

- The generation node released its worker on the first failed health probe
  of the frontend, so one slow answer during the GSM8K run could tear the
  generation worker down mid-evaluation. Require ten consecutive failed
  probes before treating the frontend as shut down.
- The OpenAI client timeout is in seconds; 1_800_000 let a stalled request
  hold a worker thread for weeks. Use 3600 s per attempt, which with the
  default two retries still ends inside the test timeout.

Signed-off-by: Lizhi Zhou <1432185+reasonsolo@users.noreply.github.com>
The fusion gate takes the Q lengths from attn_metadata.cu_q_seqlens,
which DeepSeek V4 metadata does not set, or from cu_seq_lens_cuda for
pure generation batches, so only decode batches take the fused path.
Correct the docstrings and comments that described context coverage;
the context-side handling stays in place but is not exercised yet.

Signed-off-by: Lizhi Zhou <1432185+reasonsolo@users.noreply.github.com>
…utes

The GB300 list gave test_gsm8k_dep4_megamoe_cutedsl a 240-minute
TIMEOUT. Lower it to 30 minutes, which is enough for this test on
GB300.

Signed-off-by: Lizhi Zhou <1432185+reasonsolo@users.noreply.github.com>
…ding test

mla_rope_generation now passes q_rope_applied to the kernel after
quant_scale_qkv. Cover it in the forwarded controls and compare the
trailing arguments by the controls' length instead of a fixed count.

Signed-off-by: Lizhi Zhou <1432185+reasonsolo@users.noreply.github.com>
…ning cache key

cu_q_seqlens and kv_cache_lengths are sized by the batch and were left
as static dims, so every decode batch whose size differed from the
tuning batch missed the autotuner cache and ran the fallback tactic.

The kernel takes positions from position_ids and only stages the batch
metadata, so constrain both inputs to a single tuning sequence (which
maps them to -1 in the cache key) and fill them with valid values in the
tuning pre-hook. The SM107 test now checks that a different number of
sequences with the same M hits the tuned entry.

Signed-off-by: Lizhi Zhou <1432185+reasonsolo@users.noreply.github.com>
…oRA output

- The q_b GEMM fusion gate now also requires the precomputed cu_seqlens
  hook, 128 local heads and the 448 + 64 head layout. Without the hook,
  generation would assert after the fused kernel had already run.
- The fused epilogue output is always a contiguous [tokens, 1, hidden]
  buffer, so the non-direct path no longer returns a strided slice.
  O-LoRA always goes to a separate scratch.
- Drop the unreachable copy branch in the single-phase shortcut.
- Allocate the unit FP8 Q scale as a module buffer at init instead of
  lazily, so a first call under CUDA graph capture issues no H2D copy.

Signed-off-by: Lizhi Zhou <1432185+reasonsolo@users.noreply.github.com>
…d check every q_b tactic

- An output_tensor without partition_id is a plain in-place GEMM only on
  runners that opt in (the MXFP8 in-place runner). Other runners reject
  it again, as before.
- The MXFP8 in-place runner inherits the parent's kernel cache and
  derives its tuning config from the parent, adding only the output M
  constraint.
- The q_b fusion test checks every registered tactic against the
  reference, not only the one the autotuner picked.

Signed-off-by: Lizhi Zhou <1432185+reasonsolo@users.noreply.github.com>
…ator has it

The Evaluator base class has no num_samples, so a correctly built
evaluator of another type would fail with a misleading ValueError.

Signed-off-by: Lizhi Zhou <1432185+reasonsolo@users.noreply.github.com>
…V4 on SM107

DeepseekV4ForCausalLM.get_model_defaults only returned KV cache
defaults, so on SM107 the FP8 block-scale linears fell back to the
non-CuTe DSL GEMM path and prefill ran noticeably slower, which reduced
high-concurrency disaggregated throughput.

Return use_cute_dsl_blockscaling_mm=True as a model default when
running on SM107, keeping the existing KV cache defaults logic. Update
the unit tests accordingly and add an SM107 case.

Signed-off-by: Lizhi Zhou <1432185+reasonsolo@users.noreply.github.com>
… KV slice

A DSpark generation-only request allocates room for its draft tokens
past the prompt. Add a case where only that reserve spills into a new
block, and check that the block is dropped from the transfer table
while the in-window SWA blocks keep their ordinals.

Signed-off-by: Lizhi Zhou <1432185+reasonsolo@users.noreply.github.com>
… test

Main replaced DFlashWorker._batch_to_slot with a DeviceCopyBuffer
(_batch_to_slot_buffer). The test still set the old attribute, so
prepare_1st_drafter_inputs read .tensor from None.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Lizhi Zhou <1432185+reasonsolo@users.noreply.github.com>
@reasonsolo
reasonsolo force-pushed the user/lizhiz/rubin-mb4-pr3-dsv4 branch from 83ed552 to 2237b43 Compare October 24, 2026 02:40
@reasonsolo

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #80307 [ run ] triggered by Bot. Commit: 2237b43 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #80307 [ run ] completed with state FAILURE. Commit: 2237b43
/LLM/main/L0_MergeRequest_PR pipeline #66096 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@reasonsolo

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #80341 [ run ] triggered by Bot. Commit: 2237b43 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #80341 [ run ] completed with state FAILURE. Commit: 2237b43
/LLM/main/L0_MergeRequest_PR pipeline #66124 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@reasonsolo

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #80365 [ run ] triggered by Bot. Commit: 2237b43 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #80365 [ run ] completed with state SUCCESS. Commit: 2237b43
/LLM/main/L0_MergeRequest_PR pipeline #66142 completed with status: 'FAILURE'

CI Report

⚠️ Resource Maintenance — Test Coverage Reduced:

Resource maintenance in LLM/main/L0_Test-x86_64-Multi-GPU #2991: B200 multi-GPU stages are paused to relieve the CI queue backlog (109 running / 459 pending on 2026-10-22). Owner: @sharabeshj-nvda. The CI team decides when to lift it.
Affected stages:
DGX_B200-2_GPUs-PyTorch-1
DGX_B200-4_GPUs-PyTorch-1
DGX_B200-4_GPUs-PyTorch-2
DGX_B200-4_GPUs-PyTorch-3
DGX_B200-4_GPUs-PyTorch-Ray-1
DGX_B200-8_GPUs-PyTorch-1
DGX_B200-8_GPUs-PyTorch-2
DGX_B200-8_GPUs-PyTorch-3
DGX_B200-8_GPUs-PyTorch-4
DGX_B200-8_GPUs-PyTorch-Ray-1

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@reasonsolo

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #80386 [ run ] triggered by Bot. Commit: 2237b43 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #80386 [ run ] completed with state SUCCESS. Commit: 2237b43
/LLM/main/L0_MergeRequest_PR pipeline #66162 completed with status: 'SUCCESS'

CI Report

⚠️ Resource Maintenance — Test Coverage Reduced:

Resource maintenance in LLM/main/L0_Test-x86_64-Multi-GPU #2992: B200 multi-GPU stages are paused to relieve the CI queue backlog (109 running / 459 pending on 2026-10-22). Owner: @sharabeshj-nvda. The CI team decides when to lift it.
Affected stages:
DGX_B200-2_GPUs-PyTorch-1
DGX_B200-4_GPUs-PyTorch-1
DGX_B200-4_GPUs-PyTorch-2
DGX_B200-4_GPUs-PyTorch-3
DGX_B200-4_GPUs-PyTorch-Ray-1
DGX_B200-8_GPUs-PyTorch-1
DGX_B200-8_GPUs-PyTorch-2
DGX_B200-8_GPUs-PyTorch-3
DGX_B200-8_GPUs-PyTorch-4
DGX_B200-8_GPUs-PyTorch-Ray-1

Link to invocation

@reasonsolo
reasonsolo merged commit d7e0eca into NVIDIA:main Oct 24, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api-compatible Accepted LLM API contract change that is backwards-compatible ci: full pre-merge approved

Projects

None yet

Development

Successfully merging this pull request may close these issues.