Skip to content

add out parameter for dsa api - #470

Merged
Anerudhan merged 2 commits into
NVIDIA:developfrom
terminator123:dsa_test
Aug 3, 2026
Merged

add out parameter for dsa api#470
Anerudhan merged 2 commits into
NVIDIA:developfrom
terminator123:dsa_test

Conversation

@terminator123

@terminator123 terminator123 commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Before submitting

  • I agree to license this contribution under the terms of LICENSE.txt.
  • I ran pre-commit run and committed any formatting changes.

Affected area

  • Python API or bindings

Summary

Add out parameter to indexer_forward_wrapper to enable tensor reuse across multiple calls.

This PR allows users to pass a pre-allocated output tensor for the cuDNN DSA indexer forward pass, avoiding repeated internal tensor creation when indexer_forward_wrapper is called iteratively.

Key changes:

  • Add optional output_tensor parameter to indexer_forward_wrapper
  • When provided, reuse the tensor instead of creating new ones internally
  • Maintain backward compatibility (parameter defaults to None)

Why

In Megatron-LM, _indexer_topk_from_score_chunks may call indexer_forward_wrapper in a loop during training. Without output tensor reuse, the cuDNN DSA indexer creates new output tensors on every call, leading to:

  • Memory leak-like behavior: CUDA memory cache pressure continuously increases
  • Performance degradation: Repeated allocation/deallocation overhead
  • OOM risks: Extended training runs may hit out-of-memory errors

This approach:

  • Eliminates unnecessary tensor allocations
  • Reduces CUDA memory churn
  • Improves training stability for long-running jobs

Summary by CodeRabbit

  • New Features
    • Added support for providing a preallocated output tensor when using the supported attention implementation.
    • Existing behavior remains unchanged when no output tensor is supplied.

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The indexer forward wrapper now accepts an optional out tensor and forwards it to both SM90 and SM100 implementations. The SM90 interface places sm_scale before out.

Changes

Indexer forward output

Layer / File(s) Summary
Add optional output forwarding
python/cudnn/deepseek_sparse_attention/indexer_forward/api.py, python/cudnn/deepseek_sparse_attention/indexer_forward/_interface_sm90.py
The wrapper accepts out and forwards it through both dispatch paths. The SM90 parameter order places sm_scale before out.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Suggested reviewers: anerudhan, jiayus-nvidia

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the change and motivation, but it omits the required API compatibility and testing sections and does not address related issues. Add API compatibility details, exact testing commands and results, and a related-issues entry or state that none apply; use the actual parameter name consistently.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: adding an output parameter to the DSA API.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@python/cudnn/deepseek_sparse_attention/indexer_forward/api.py`:
- Line 227: Update the docstring for the wrapper containing the out parameter to
state that output allocation occurs only when out is None; when provided, out
must have the exact expected shape, torch.float32 dtype, CUDA storage, and
contiguous layout.
- Line 227: Update the affected function signature in the indexer forward API so
the new optional out parameter is appended after q_causal_offsets, rather than
inserted before m_block_size. Preserve the existing positional order of all
tuning parameters and keep out optional.
- Line 270: Update the SM100 dispatch wrapper call to indexer_fwd to pass the
existing out buffer as out=out, ensuring the caller-provided output receives the
computed result.
🪄 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: Enterprise

Run ID: e26a8c47-3ca9-4fbb-877a-42c6cbdaf455

📥 Commits

Reviewing files that changed from the base of the PR and between 073ce27 and 9852848.

📒 Files selected for processing (1)
  • python/cudnn/deepseek_sparse_attention/indexer_forward/api.py

w: torch.Tensor,
ratio: int = 4,
qhead_per_kv_head: Optional[int] = None,
out: Optional[torch.Tensor] = None,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Document the out contract.

The docstring says that the wrapper allocates the output buffer, but out bypasses allocation. Document that allocation occurs only when out is None. Also document the SM90 requirements: exact output shape, torch.float32, CUDA storage, and contiguous layout.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@python/cudnn/deepseek_sparse_attention/indexer_forward/api.py` at line 227,
Update the docstring for the wrapper containing the out parameter to state that
output allocation occurs only when out is None; when provided, out must have the
exact expected shape, torch.float32 dtype, CUDA storage, and contiguous layout.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Preserve the existing positional parameter layout.

out is inserted before m_block_size. Existing positional callers now bind tuning parameters to the wrong arguments. Append out after q_causal_offsets so existing calls remain compatible.

Proposed signature change
     q_causal_offsets: Optional[torch.Tensor] = None,
+    out: Optional[torch.Tensor] = None,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@python/cudnn/deepseek_sparse_attention/indexer_forward/api.py` at line 227,
Update the affected function signature in the indexer forward API so the new
optional out parameter is appended after q_causal_offsets, rather than inserted
before m_block_size. Preserve the existing positional order of all tuning
parameters and keep out optional.

Comment thread python/cudnn/deepseek_sparse_attention/indexer_forward/api.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@python/cudnn/deepseek_sparse_attention/indexer_forward/api.py`:
- Line 232: Move the out parameter in indexer_forward/api.py:232 and
indexer_forward/_interface_sm90.py:51 out of the middle of each callable
signature by making it keyword-only or appending it after q_causal_offsets in
api.py and after current_stream in _interface_sm90.py; preserve all existing
positional argument bindings.
🪄 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: Enterprise

Run ID: 6ae61b93-2978-4eab-b939-e1952e0539cf

📥 Commits

Reviewing files that changed from the base of the PR and between 9852848 and 53091b2.

📒 Files selected for processing (2)
  • python/cudnn/deepseek_sparse_attention/indexer_forward/_interface_sm90.py
  • python/cudnn/deepseek_sparse_attention/indexer_forward/api.py

q_stage: int = 2,
kv_stage: int = 4,
sm_scale: float = 1.0,
out: Optional[torch.Tensor] = None,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
for f in \
  python/cudnn/deepseek_sparse_attention/indexer_forward/api.py \
  python/cudnn/deepseek_sparse_attention/indexer_forward/_interface_sm90.py
do
  echo "=== $f ==="
  sed -n '205,255p' "$f" 2>/dev/null || true
  sed -n '25,75p' "$f" 2>/dev/null || true
done

echo "=== definitions and call sites ==="
rg -n --glob '*.py' \
  'def (indexer_forward|.*indexer.*forward)|IndexerForward|indexer_forward\(' \
  python test 2>/dev/null | head -250

Repository: NVIDIA/cudnn-frontend

Length of output: 8739


🏁 Script executed:

#!/bin/bash
set -eu
python3 - <<'PY'
import ast
from pathlib import Path

files = [
    Path("python/cudnn/deepseek_sparse_attention/indexer_forward/api.py"),
    Path("python/cudnn/deepseek_sparse_attention/indexer_forward/_interface_sm90.py"),
]
for path in files:
    print(f"=== {path} ===")
    tree = ast.parse(path.read_text())
    for node in ast.walk(tree):
        if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
            if node.name in {"__call__", "execute", "indexer_forward"} or "forward" in node.name:
                args = node.args
                positional = args.posonlyargs + args.args
                defaults = [None] * (len(positional) - len(args.defaults)) + list(args.defaults)
                print(node.name, node.lineno)
                print("  positional:", [(a.arg, ast.unparse(d) if d else None) for a, d in zip(positional, defaults)])
                print("  kwonly:", [a.arg for a in args.kwonlyargs])
PY

Repository: NVIDIA/cudnn-frontend

Length of output: 870


🏁 Script executed:

#!/bin/bash
set -eu
python3 - <<'PY'
import ast
from pathlib import Path

targets = [
    Path("python/cudnn/deepseek_sparse_attention/indexer_forward/api.py"),
    Path("python/cudnn/deepseek_sparse_attention/indexer_forward/_interface_sm90.py"),
]
for path in targets:
    print(f"=== {path} ===")
    text = path.read_text()
    tree = ast.parse(text)
    for node in ast.walk(tree):
        if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
            if node.lineno <= 260:
                args = node.args
                positional = args.posonlyargs + args.args
                defaults = [None] * (len(positional) - len(args.defaults)) + list(args.defaults)
                print(
                    node.name,
                    node.lineno,
                    "positional=",
                    [(a.arg, ast.unparse(d) if d else None) for a, d in zip(positional, defaults)],
                    "kwonly=",
                    [a.arg for a in args.kwonlyargs],
                )
PY
echo "=== all references ==="
rg -n --glob '*.py' 'indexer_forward|IndexerForward|_interface_sm90' . | head -300

Repository: NVIDIA/cudnn-frontend

Length of output: 7192


🏁 Script executed:

#!/bin/bash
set -eu
echo "=== wrapper dispatch and output handling ==="
sed -n '245,345p' python/cudnn/deepseek_sparse_attention/indexer_forward/api.py
echo "=== SM90 interface implementation ==="
sed -n '40,175p' python/cudnn/deepseek_sparse_attention/indexer_forward/_interface_sm90.py
echo "=== test call shapes ==="
sed -n '50,180p' test/python/fe_api/dsa/test_DSA_indexer_forward.py

Repository: NVIDIA/cudnn-frontend

Length of output: 12496


Do not insert out into the middle of either callable signature.

Make out keyword-only, or append it after q_causal_offsets in api.py and after current_stream in _interface_sm90.py. This preserves existing positional bindings.

📍 Affects 2 files
  • python/cudnn/deepseek_sparse_attention/indexer_forward/api.py#L232-L232 (this comment)
  • python/cudnn/deepseek_sparse_attention/indexer_forward/_interface_sm90.py#L51-L51
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@python/cudnn/deepseek_sparse_attention/indexer_forward/api.py` at line 232,
Move the out parameter in indexer_forward/api.py:232 and
indexer_forward/_interface_sm90.py:51 out of the middle of each callable
signature by making it keyword-only or appending it after q_causal_offsets in
api.py and after current_stream in _interface_sm90.py; preserve all existing
positional argument bindings.

@Anerudhan
Anerudhan self-requested a review August 3, 2026 20:47
@Anerudhan Anerudhan assigned Anerudhan and terminator123 and unassigned Anerudhan Aug 3, 2026
@Anerudhan Anerudhan added orig-external Reported or requested by an external user, customer, or community contributor. mod-cutedsl CuTeDSL kernels, generated kernels, examples, or related integration work. cat-enhancements labels Aug 3, 2026
@Anerudhan Anerudhan added this to the Frontend 1.27.0 milestone Aug 3, 2026
@Anerudhan
Anerudhan merged commit e7c7834 into NVIDIA:develop Aug 3, 2026
1 check passed
@Anerudhan Anerudhan mentioned this pull request Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cat-enhancements mod-cutedsl CuTeDSL kernels, generated kernels, examples, or related integration work. orig-external Reported or requested by an external user, customer, or community contributor.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants