[TRTLLM-34871][feat] Add cute dsl FP8 paged MQA logits decode kernel#13219
Conversation
…M100 Replace DeepGEMM-based indexer logits with a CuTE DSL kernel on SM100+, gated by `use_cute_dsl_logits` config flag. Includes kernel implementation, PyTorch custom op registration, config plumbing, and unit tests. Signed-off-by: Mindy Li <11663212+limin2021@users.noreply.github.com>
Replace stale development script name with the actual module filename. Signed-off-by: Mindy Li <11663212+limin2021@users.noreply.github.com>
Signed-off-by: Mindy Li <11663212+limin2021@users.noreply.github.com>
Signed-off-by: Mindy Li <11663212+limin2021@users.noreply.github.com>
📝 WalkthroughWalkthroughThis change introduces a new CuTE DSL-based FP8 paged MQA logits kernel for SM100+ GPUs as an alternative to the existing C++ implementation. Configuration, custom op registration, kernel integration in the sparse attention indexer, and comprehensive test coverage are added. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tensorrt_llm/_torch/model_config.py (1)
526-548:⚠️ Potential issue | 🟡 MinorAdd the required NVIDIA SPDX header to this modified file.
This file is modified in this PR but still has no NVIDIA copyright header at the top. Please add/update it in the same change so the file stays repo-compliant.
As per coding guidelines,
**/*.{h,hpp,cpp,cc,cxx,cu,py}: All TensorRT-LLM source files must contain an NVIDIA copyright header with the year of latest meaningful modification.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tensorrt_llm/_torch/model_config.py` around lines 526 - 548, Add the required NVIDIA SPDX copyright header to the top of tensorrt_llm/_torch/model_config.py (the file modified in this PR) by inserting the standard NVIDIA SPDX header block including the correct copyright year (use the year of the latest meaningful modification) and SPDX identifier; ensure the header appears before any imports or code so the module (including classes/functions like DeepSeekSparseAttentionConfig and the surrounding kwargs handling) is repo-compliant and save the file with that header included.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@tensorrt_llm/_torch/attention_backend/sparse/dsa.py`:
- Around line 1114-1117: The logits path can call
torch.ops.trtllm.cute_dsl_fp8_paged_mqa_logits before the custom op is
registered because cute_dsl_custom_ops is only imported under the independent
use_cute_dsl_topk branch; to fix this, ensure the module is explicitly imported
when use_cute_dsl_logits is true (before invoking
torch.ops.trtllm.cute_dsl_fp8_paged_mqa_logits) by adding an import of
cute_dsl_custom_ops from tensorrt_llm._torch.custom_ops in the branch guarded by
self.use_cute_dsl_logits (so use_cute_dsl_logits, cute_dsl_custom_ops, and the
call to torch.ops.trtllm.cute_dsl_fp8_paged_mqa_logits are all referenced).
In `@tensorrt_llm/_torch/custom_ops/cute_dsl_custom_ops.py`:
- Around line 5290-5317: The cute_dsl_fp8_paged_mqa_logits wrapper must validate
the GPU SM/architecture before dispatch like the other Blackwell-only ops;
update the function (or immediately before calling
CuteDSLPagedMQALogitsRunner.forward) to check the current device's SM/compute
capability (reuse the same helper or check used by other *_blackwell wrappers)
and raise a clear, early exception if the GPU is not Blackwell (or not
supported), rather than proceeding to call CuteDSLPagedMQALogitsRunner.forward;
ensure the error message references this op name and suggests disabling
use_cute_dsl_logits or using a supported GPU.
- Around line 5267-5288: The code creates a fresh stream (torch_stream =
torch.cuda.Stream()) and synchronizes the device, causing data races and a
global barrier; instead use the caller's current CUDA stream: replace creating a
new torch.cuda.Stream() with torch.cuda.current_stream() (so torch_stream
variable refers to torch.cuda.current_stream()), keep constructing the
cuda.CUstream from that stream, pass that stream into the compiled kernel launch
(the compiled(*dl_args, num_phys_blocks, B, stream) call), and remove the
unconditional torch.cuda.synchronize() so we don't impose a device-wide barrier;
ensure the compile/cache logic (cls._compile, cls.kernel_cache,
cls._make_dlpacks, compiled) still works with the caller stream and let callers
manage any required synchronization.
In `@tensorrt_llm/_torch/cute_dsl_kernels/blackwell/paged_mqa_logits/__init__.py`:
- Line 16: Add an explicit module export list to document the public API: update
the package __init__ by defining __all__ = ["FP8MQALogitsDGFullKKernel"] so the
re-export of FP8MQALogitsDGFullKKernel from fp8_paged_mqa_logits becomes
explicit and avoids F401/implicit API issues; keep the existing import statement
(from .fp8_paged_mqa_logits import FP8MQALogitsDGFullKKernel) and add the
__all__ declaration in the same module.
In
`@tests/unittest/_torch/attention/sparse/test_cute_dsl_fp8_paged_mqa_logits.py`:
- Around line 185-187: The current skip marker skip_if_unsupported gates the
whole test on has_deep_gemm(), which wrongly prevents running the CuTe DSL
kernel when DeepGEMM is absent; change the skip condition to only require
IS_CUTLASS_DSL_AVAILABLE so tests run when CuTe DSL/hardware is present (i.e.,
skip_if_unsupported = pytest.mark.skipif(not IS_CUTLASS_DSL_AVAILABLE,
reason="Requires CuTe DSL/hardware")); then update the test’s reference
selection to pick the best available reference at runtime (use has_deep_gemm()
to choose the DeepGEMM reference if available, otherwise fall back to the pure
PyTorch reference) so the test exercises the CuTe DSL kernel while still
comparing against a valid fallback.
---
Outside diff comments:
In `@tensorrt_llm/_torch/model_config.py`:
- Around line 526-548: Add the required NVIDIA SPDX copyright header to the top
of tensorrt_llm/_torch/model_config.py (the file modified in this PR) by
inserting the standard NVIDIA SPDX header block including the correct copyright
year (use the year of the latest meaningful modification) and SPDX identifier;
ensure the header appears before any imports or code so the module (including
classes/functions like DeepSeekSparseAttentionConfig and the surrounding kwargs
handling) is repo-compliant and save the file with that header included.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 12b7da53-887c-4a0e-b1e7-fe0d6e847a18
📒 Files selected for processing (7)
tensorrt_llm/_torch/attention_backend/sparse/dsa.pytensorrt_llm/_torch/custom_ops/cute_dsl_custom_ops.pytensorrt_llm/_torch/cute_dsl_kernels/blackwell/paged_mqa_logits/__init__.pytensorrt_llm/_torch/cute_dsl_kernels/blackwell/paged_mqa_logits/fp8_paged_mqa_logits.pytensorrt_llm/_torch/model_config.pytensorrt_llm/llmapi/llm_args.pytests/unittest/_torch/attention/sparse/test_cute_dsl_fp8_paged_mqa_logits.py
- Use current_stream() instead of creating a new stream to avoid data races - Remove unnecessary torch.cuda.synchronize() - Add is_sm_100f() check in custom op to fail fast on unsupported GPUs - Rename FP8MQALogitsDGFullKKernel to FP8MQALogitsKernel - Add __all__ to paged_mqa_logits __init__.py - Fix test skip logic to precisely match SM 100/103 only Signed-off-by: Mindy Li <11663212+limin2021@users.noreply.github.com>
…s enabled Broaden the cute_dsl_custom_ops import guard to also trigger when use_cute_dsl_logits is True, so the custom op is registered even when use_cute_dsl_topk is False. Signed-off-by: Mindy Li <11663212+limin2021@users.noreply.github.com>
|
/bot run |
…_logits Align config field name with the op name cute_dsl_fp8_paged_mqa_logits for clarity. Signed-off-by: Mindy Li <11663212+limin2021@users.noreply.github.com>
|
PR_Github #44629 [ run ] triggered by Bot. Commit: |
The custom op already validates SM 100/103 via is_sm_100f(). Also replace getattr with direct attribute access to match use_cute_dsl_topk style. Signed-off-by: Mindy Li <11663212+limin2021@users.noreply.github.com>
…ser-facing strings Remove DeepGEMM and DG-FullK references from module docstring, class docstring, function docstrings, print statements, and argparse descriptions. Inline implementation comments retained as design cross-references. Signed-off-by: Mindy Li <11663212+limin2021@users.noreply.github.com>
|
/bot run |
|
PR_Github #44637 [ run ] triggered by Bot. Commit: |
|
PR_Github #44629 [ run ] completed with state |
|
/bot run |
|
PR_Github #44645 [ run ] triggered by Bot. Commit: |
|
PR_Github #44637 [ run ] completed with state |
|
/bot run |
|
PR_Github #46879 [ run ] triggered by Bot. Commit: |
|
PR_Github #46879 [ run ] completed with state
|
|
/bot run |
1 similar comment
|
/bot run |
|
PR_Github #46943 [ run ] triggered by Bot. Commit: |
|
PR_Github #46943 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #47078 [ run ] triggered by Bot. Commit: |
|
PR_Github #47078 [ run ] completed with state
|
…xer_gemm Resolve conflicts in DSA paged-MQA-logits dispatch and tests after DeepGEMM submodule bump (4ff3f54d -> c491439e via PR NVIDIA#13340 / DG NVIDIA#304): - dsa.py: take upstream's scheduler_metadata_buffer / _full_next_n selection (mtp3 buffer removed); add DSL early-branch using the existing scheduler_metadata_buffer (built with (num_gen, 1) shape, num_atoms=1, matching DSL's 1-atom-per-q design) and the 1D kv_lens_cuda_runtime slice for context_lens. - dsa.py: introduce module-level _DG_SCHEDULE_BLOCK_KV = 64, used by all 6 get_paged_mqa_logits_metadata calls (3 in on_update_kv_lens(), 3 in Indexer.prepare()) instead of cache tokens_per_block. Decouples schedule SPLIT_KV from cache page size and side-steps a SM100 + block_kv=32 latent regression in DG commit 7f2a703 (NVIDIA#304). - test_dsa_indexer.py: take upstream's scheduler buffer selection; DSL test branch reads scheduler_metadata_buffer + 1D kv_lens. - test_cute_dsl_fp8_paged_mqa_logits.py: 4 metadata calls now pass 2D context_lens via .unsqueeze(-1) and DG_METADATA_BLOCK_KV=64; DG bench drops cluster(2,1,1) for next_n=4 (SM100 always uses num_kv_multicast=1) and passes 2D context_lens to fp8_paged_mqa_logits. Signed-off-by: Mindy Li <11663212+limin2021@users.noreply.github.com>
|
/bot run --disable-fail-fast |
|
PR_Github #47224 [ run ] triggered by Bot. Commit: |
|
PR_Github #47224 [ run ] completed with state
|
… MQA next_n coverage
test_dsa_indexer: separate scheduler_metadata_buffer for DSL backend (kNumNextNAtoms=1)
to avoid the next_n>1 alias used by DeepGEMM. Fixes test_indexer_decode_with_paged_kv_cache
across {deepgemm, dsl} x {(4,1),(2,2),(4,3),(4,4)}.
test_cute_dsl_fp8_paged_mqa_logits: extend multi_block next_n coverage to {1,2,3,4};
drop now-obsolete next_n==3 expansion in bench (newer DeepGEMM supports it natively);
update --block_kv default from 128 to 64 to match the new {32,64} assertion in
fp8_paged_mqa_logits.
Signed-off-by: Mindy Li <11663212+limin2021@users.noreply.github.com>
|
/bot run |
|
PR_Github #47317 [ run ] triggered by Bot. Commit: |
|
PR_Github #47317 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #47386 [ run ] triggered by Bot. Commit: |
|
PR_Github #47386 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #47451 [ run ] triggered by Bot. Commit: |
|
PR_Github #47451 [ run ] completed with state |
…VIDIA#13219) Signed-off-by: Mindy Li <11663212+limin2021@users.noreply.github.com>
@coderabbitai summary
Description
https://jirasw.nvidia.com/browse/CFK-34871
Summary
Key design details
Test plan
TODO:
1.e2e accuracy test for fp32 and fp16 output dtype.
Benchmark results (B200, SM count=148)
batch ctx next_n nblk | DSL(us) DG(fp32,us) DG/DSL
batch ctx next_n nblk | DSL(us) DG(fp32,us) DG/DSL DSL(fp32,us) DSL(fp32)/DSL
Test Coverage
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)
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.