Skip to content

[None][perf] Overlap DSA heuristic prev_topk write-back on the aux stream - #16666

Open
longcheng-nv wants to merge 1 commit into
NVIDIA:mainfrom
longcheng-nv:perf/prevtopk-aux-stream-copy
Open

[None][perf] Overlap DSA heuristic prev_topk write-back on the aux stream#16666
longcheng-nv wants to merge 1 commit into
NVIDIA:mainfrom
longcheng-nv:perf/prevtopk-aux-stream-copy

Conversation

@longcheng-nv

@longcheng-nv longcheng-nv commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Description

The per-layer heuristic top-k feedback copy in Indexer.sparse_attn_indexer
(this step's decode top-k → next step's pre_idx hint,
metadata.heuristic_prev_topk[local_layer].copy_(...)) is a strided gather
that sits on the main stream's critical path, once per indexer layer per
decode step. Nothing in the current step consumes it — the next reader is the
next decode step's same layer — so this PR forks it onto the Indexer's
existing aux stream right after the top-k kernel and joins it in the same
layer's MLA forward once core sparse attention has been enqueued. The copy
then overlaps with the layer's heaviest decode work instead of delaying it.

Design points:

  • Same-layer fork/join. Every fork is matched with a join inside a single
    forward, which CUDA graph capture requires (cudaStreamEndCapture rejects
    unjoined forks), and the join restores ordering before the next layer
    overwrites the shared topk_indices_buffer rows the copy reads. No
    cross-layer or cross-step event state is needed.
  • Stable-address buffers only. Source and destination are persistent
    graph-pool buffers; the captured copy stays valid on every replay and no
    record_stream bookkeeping is needed.
  • Gated on do_multi_stream(), matching maybe_execute_in_parallel
    policy: the fork engages inside CUDA graph capture (where replay makes the
    stream/event host overhead free); eager execution keeps the original inline
    copy byte-for-byte.
  • Covers both consumers: the DSA (V3.2) path in forward_dsa_attn and the
    DeepSeek-V4 path in forward_impl_with_deepseek_v4; DSA "shared" indexer
    layers (indexer is None) are unaffected.

This also benefits the upcoming GVR top-k e2e wiring (#16420), which consumes
the same heuristic_prev_topk feedback loop.

Test Coverage

  • Pattern-level CUDA graph smoke (standalone): capture with the same-layer
    join succeeds; replayed feedback values are step-correct across replays
    (write@replay N is read@replay N+1); capture without the join fails
    with cudaErrorStreamCaptureUnjoined — confirming the join placement is
    load-bearing, not defensive.
  • Existing e2e coverage: test_fp8_blockscale[heuristic_topk_mtp1]
    (TestDeepSeekV32, cuda_graph=True) exercises the forked path end-to-end
    on Blackwell.

Performance Evidence (measured)

Paired interleaved A/B, 8xB200 (TEP8, BS=1), DeepSeek-V3.2-Exp FP4, one
SWE-bench prompt (ISL 68,656 tokens), OSL 1024, CUDA graphs +
enable_heuristic_topk: true in both arms. Arms differ only in this PR's two
files (same build; per-repetition file swap, hashes logged); baseline arm runs
first in each pair. Each MTP config runs on a single node (pairs are
within-node; absolute times are not compared across nodes). Warm-up pairs
carrying first-load cost are excluded; TTFT (unaffected by this decode-only
change) is matched across arms in every reported pair.

MTP warm pairs TPOT baseline (ms) TPOT this PR (ms) mean TPOT reduction SD wins
0 3 ~9.71 ~9.40 +3.12% 0.19% 3/3
1 9 ~5.95 ~5.81 +2.26% 0.57% 9/9
2 1 (preliminary) 4.829 4.637 +3.97% n/a 1/1

The MTP=2 entry is a single TTFT-matched pair; its sweep was interrupted and
is being rerun. Remaining MTP 2-3 pairs on the same protocol will be added.

Per-pair data

MTP=0 (node A; pair 0 excluded as cold-start — its baseline leg carried
first-load cost, TTFT 20.9 s vs 3.15 s):

pair TPOT baseline TPOT PR reduction
1 9.6916 9.4100 +2.91%
2 9.7162 9.4036 +3.22%
3 9.7148 9.3994 +3.25%

MTP=1 (node B; pair 1 showed no cold-start contamination — TTFT matched —
but is excluded for protocol consistency; including it: +2.30% over 10 pairs,
10/10 wins):

pair TPOT baseline TPOT PR reduction
1 6.0012 5.8429 +2.64% (excluded)
2 5.8873 5.8138 +1.25%
3 5.9602 5.7932 +2.80%
4 5.9554 5.7850 +2.86%
5 5.9434 5.7961 +2.48%
6 5.9611 5.8362 +2.10%
7 5.9515 5.8239 +2.14%
8 5.9269 5.8290 +1.65%
9 5.9551 5.7793 +2.95%
10 5.9483 5.8230 +2.11%

MTP=2 (node B; sweep interrupted after pair 1, rerun in progress; TTFT
matched, 3324.5 vs 3321.2 ms):

pair TPOT baseline TPOT PR reduction
1 4.8290 4.6373 +3.97%

PR Checklist

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

Dev Engineer Review

  • Added auxiliary-stream fork/join handling for heuristic TopK copy in DSA and DeepSeek-V4 paths.
  • Preserved synchronous copying when do_multi_stream() is disabled.
  • Preserved CUDA graph capture and persistent graph-pool buffer usage.
  • Added Indexer.maybe_join_prev_topk_copy() with pending-state cleanup.
  • The DSA and DeepSeek-V4 join points occur after core attention enqueue, which preserves stream ordering.
  • Shared DSA indexer layers remain unchanged.
  • Reported paired measurements show TPOT reductions of 3.12% for MTP=0, 2.26% for MTP=1, and 3.97% for one preliminary MTP=2 pair, with matched TTFT.
  • No configuration or test-list changes were identified.
  • Three CI runs failed. The failures require investigation before merge.

QA Engineer Review

No test changes.

@longcheng-nv
longcheng-nv force-pushed the perf/prevtopk-aux-stream-copy branch 2 times, most recently from 767b036 to 90c4b5c Compare August 6, 2026 03:03
@longcheng-nv
longcheng-nv marked this pull request as ready for review August 6, 2026 03:03
@longcheng-nv
longcheng-nv requested a review from a team as a code owner August 6, 2026 03:03
@longcheng-nv

Copy link
Copy Markdown
Collaborator Author

/bot run

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 1850890b-026b-4558-9f93-714a99e13b4d

📥 Commits

Reviewing files that changed from the base of the PR and between 937bacc and 52d3f9b.

📒 Files selected for processing (3)
  • tensorrt_llm/_torch/attention_backend/sparse/deepseek_v4/module.py
  • tensorrt_llm/_torch/attention_backend/sparse/dsa/indexer.py
  • tensorrt_llm/_torch/attention_backend/sparse/dsa/module.py

Walkthrough

The change adds asynchronous heuristic TopK write-back coordination to Indexer. DSA and DeepSeek-V4 sparse attention paths join pending copies after scheduling core attention work.

Changes

DSA TopK write-back

Layer / File(s) Summary
Asynchronous TopK copy coordination
tensorrt_llm/_torch/attention_backend/sparse/dsa/indexer.py
Indexer adds CUDA events and pending state. Decode write-back uses aux_stream when multi-stream execution is enabled and retains synchronous copying otherwise. A join method clears pending state after synchronization.
Sparse attention forward-path synchronization
tensorrt_llm/_torch/attention_backend/sparse/dsa/module.py, tensorrt_llm/_torch/attention_backend/sparse/deepseek_v4/module.py
Both sparse attention paths call maybe_join_prev_topk_copy() after core attention scheduling when an indexer is present.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: qijune, kris1025

Sequence Diagram(s)

sequenceDiagram
  participant SparseAttention
  participant Indexer
  participant aux_stream
  participant CUDA_events
  SparseAttention->>Indexer: Schedule heuristic TopK write-back
  Indexer->>aux_stream: Fork asynchronous copy
  aux_stream->>CUDA_events: Record copy completion
  SparseAttention->>Indexer: maybe_join_prev_topk_copy()
  Indexer->>CUDA_events: Wait for pending copy
  CUDA_events-->>Indexer: Signal completion
  Indexer-->>SparseAttention: Clear pending state
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise, specific, and accurately describes overlapping DSA heuristic TopK write-back on the auxiliary stream.
Description check ✅ Passed The description explains the problem, solution, design constraints, test coverage, performance evidence, and checklist status in sufficient detail.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64192 [ run ] triggered by Bot. Commit: 90c4b5c Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64192 [ run ] completed with state FAILURE. Commit: 90c4b5c
/LLM/main/L0_MergeRequest_PR pipeline #52105 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

@longcheng-nv

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64243 [ run ] triggered by Bot. Commit: 90c4b5c Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64243 [ run ] completed with state FAILURE. Commit: 90c4b5c
/LLM/main/L0_MergeRequest_PR pipeline #52149 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

@longcheng-nv
longcheng-nv force-pushed the perf/prevtopk-aux-stream-copy branch from 90c4b5c to 4d90b7b Compare August 7, 2026 01:32
@longcheng-nv

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64444 [ run ] triggered by Bot. Commit: 4d90b7b Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64444 [ run ] completed with state FAILURE. Commit: 4d90b7b
/LLM/main/L0_MergeRequest_PR pipeline #52320 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

…ream

The per-layer heuristic top-k feedback copy (this step's decode top-k
-> next step's pre_idx hint) is a strided gather sitting on the main
stream's critical path, once per indexer layer per decode step. Nothing
in the current step consumes it, so fork it onto the Indexer's existing
aux stream right after the top-k kernel and join it in the same layer's
MLA forward once core sparse attention is enqueued -- the copy overlaps
with the layer's heaviest decode work.

Same-layer fork/join keeps CUDA graph capture free of unjoined forks
(cudaStreamEndCapture rejects them) and restores ordering before the
next layer overwrites the shared topk_indices_buffer rows the copy
reads. Source and destination are persistent stable-address buffers, so
replays stay valid with no record_stream bookkeeping.

The fork engages only under do_multi_stream() (i.e. inside CUDA graph
capture, where replay makes the stream/event host overhead free); eager
execution keeps the original inline copy unchanged.

Validated with a pattern-level CUDA graph smoke test: capture with the
join succeeds, replayed feedback values are step-correct, and capture
without the join fails with cudaErrorStreamCaptureUnjoined.

Ported onto the sparse-attention framework refactor (NVIDIA#12733): the
Indexer changes moved from sparse/dsa.py to sparse/dsa/indexer.py, and
the two MLA join sites moved from modules/mla.py to
sparse/dsa/module.py (_forward_dsa_attn) and
sparse/deepseek_v4/module.py (forward_sparse_attn).

Made-with: Claude Code (Fable 5)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: longcheng-nv <243710427+longcheng-nv@users.noreply.github.com>
@longcheng-nv
longcheng-nv force-pushed the perf/prevtopk-aux-stream-copy branch from 4d90b7b to 52d3f9b Compare August 8, 2026 07:37
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@longcheng-nv

Copy link
Copy Markdown
Collaborator Author

Rebased/ported onto the sparse-attention framework refactor (#12733), new head 52d3f9b: the Indexer fork moved from sparse/dsa.py to sparse/dsa/indexer.py (single site now covers both V3.2 and the DeepseekV4Indexer subclass), and the two same-layer join sites moved from modules/mla.py to sparse/dsa/module.py::_forward_dsa_attn and sparse/deepseek_v4/module.py::forward_sparse_attn. Logic is unchanged (diff-of-diffs is the import split only). This also picks up #17416, which fixes the test_on_update_kv_lens_rebuilds_stale_map stub failure that hit the previous CI run on main-side code.

@longcheng-nv

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64772 [ run ] triggered by Bot. Commit: 52d3f9b Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64772 [ run ] completed with state FAILURE. Commit: 52d3f9b
/LLM/main/L0_MergeRequest_PR pipeline #52616 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

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.

2 participants