Skip to content

[PyTorch] GDN2 support and linear attention refactor - #3521

Open
ksivaman wants to merge 11 commits into
NVIDIA:mainfrom
ksivaman:gdn2_attention
Open

ksivaman wants to merge 11 commits into
NVIDIA:mainfrom
ksivaman:gdn2_attention

Conversation

@ksivaman

@ksivaman ksivaman commented Sep 15, 2026

Copy link
Copy Markdown
Member

Description

Adds support for GDN2 variant and redesign the linear attention API.

Type of change

  • Documentation change (change only to the documentation, either a fix or a new content)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Infra/Build change
  • Code refactoring

Changes

  • Integrate fused GDN2 kernel from cudnn-frontend (v1.29.0 required).
  • Linear attention base module.

Checklist:

  • I have read and followed the contributing guidelines
  • The functionality is complete
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Signed-off-by: Kirthi Shankar Sivamani <ksivamani@nvidia.com>
Signed-off-by: Kirthi Shankar Sivamani <ksivamani@nvidia.com>
@greptile-apps

greptile-apps Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

The PR does not yet appear safe to merge because the previously reported required-runtime installation gap remains unresolved; the new architecture wording should also be corrected.

Findings

  1. P1 FSDP setup calls missing method
  2. P1 Required runtime is not installed
  3. P1 FP8 Test Fails Early
  4. P2 Architecture Support Is Overstated

Summary

Adds Gated DeltaNet v2 through the cuDNN frontend and refactors linear-attention variants around shared layout validation, lifecycle handling, recurrent-state support, checkpointing, and CUDA-graph integration.

  • Exposes and documents the new GatedDeltaNet2Attention API.
  • Adds dense and packed-layout GDN2 coverage, including state continuation and backward checks.
  • Raises the cuDNN frontend dependency floor to 1.29.0.
  • Extends TransformerEngine distributed and graph infrastructure to recognize parameter-free linear-attention modules.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    U[Linear-attention caller] --> B[LinearAttentionBase]
    B --> V[Lifecycle and input validation]
    V --> A[Variant kernel adapter]
    A --> G1[cuDNN GDN op]
    A --> G2[cuDNN GDN2 op]
    G1 --> O[Output and optional final state]
    G2 --> O
Loading

Reviews (8) · Last reviewed commit: "docsting"

LayerNorm,
RMSNorm,
TransformerEngineBaseModule,
LinearAttentionBase,

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.

P1 FSDP setup calls missing method

Adding LinearAttentionBase to the TE-class registry makes directly or individually FSDP-wrapped GDN modules enter prepare_te_modules_for_fsdp. That function unconditionally calls fast_setattr, but the new base is a plain torch.nn.Module and does not implement this method. FSDP preparation therefore raises AttributeError before the model can run.

Comment thread build_tools/pytorch.py
"pydantic",
"nvdlfw-inspect",
"nvidia-cudnn-frontend>=1.28.0",
"nvidia-cudnn-frontend>=1.29.0",

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.

P1 Required runtime is not installed

GDN2 explicitly requires the cuDNN frontend cutedsl runtime, but both installation declarations request only the base nvidia-cudnn-frontend package. If that base package does not include the optional cutlass runtime, the newly mandatory L0 GDN2 test fails during collection and the advertised feature cannot run.

Comment thread transformer_engine/pytorch/attention/linear_attention/gdn2.py
@ksivaman
ksivaman marked this pull request as draft September 15, 2026 19:02
Signed-off-by: Kirthi Shankar Sivamani <ksivamani@nvidia.com>
Signed-off-by: Kirthi Shankar Sivamani <ksivamani@nvidia.com>
@ksivaman
ksivaman marked this pull request as ready for review September 15, 2026 20:56
attention(q, k, v, g=g, beta=beta)


def test_gdn2_rejects_fp8_autocast():

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.

P1 FP8 Test Fails Early

On a CUDA device where FP8 is unavailable, autocast(enabled=True) raises RuntimeError while entering the context, before GDN2 can raise the expected ValueError. Because this test no longer checks FP8 availability, it fails on those supported test configurations instead of validating the module's FP8 rejection behavior.

Signed-off-by: Kirthi Shankar Sivamani <ksivamani@nvidia.com>
@ksivaman

Copy link
Copy Markdown
Member Author

/te-ci pytorch

@KshitijLakhani KshitijLakhani 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.

  1. Can we consider moving both gdn and gdn2 tests into the same linear attention file for testing and then we can just add the newer linear attention types to it in the future. I'm also assuming here that the tests could share some setup/boilerplate info (e.g. is gdn/gdn op available ?) .
    The other (maybe preferred) option is to have a these separate as you currently have them and then have a shared test file/class in which the shared utilities could cover (for e.g.) :
    i) RMS comparison helpers.
    ii) THD input conversion.
    iii) TP/lifecycle tests.
    iv) Checkpointing tests.
    v) Common output-shape/layout conformance.

  2. nit: I understand this might be for simplicity in interest of time that even thought cuDNN GDN2 supports distinct Q, K and V head counts, the TE wrapper requires all head counts to be equal, but please one of the following - i) Add this support (ideal) or ii) Add a TODO and add either Charlene or my name for it for the future) . And on the same note, I learnt from my agent that cuDNN GDN API seems to be supporting a a lot of other args, but I'm guessing yoau are intentionally using a minimal GDN2 API ??

  3. This is not supposed to be a blocker for this PR but @cyanguwa I think it would make sense to have a plan for integration into upper Transformer Layers ? (right now it is DPA/MHA hard-coded but we might have to change it with linear / spare right ?)
    Something liek this:
    TransformerLayer

    ├── MultiheadAttention
    │     QKV projection → DPA → output projection
    │
    └── GDN2 attention block
          QKV + gate projections → GDN2 core → output projection
  1. Non-blocking: I understand the hesitation to refactor TransformerEngineBaseModule, especially since it is central and has been relatively stable. Keeping LinearAttentionBase separate is reasonable for this PR and avoids pulling unused FP8 state into parameter-free LA kernels.

My concern is less the duplicated implementation and more that this creates a second module type participating in TE-wide lifecycle behavior. This PR already updates get_te_classes(), CUDA-graph discovery, and implements the FSDP fast_setattr contract. Future framework-level code could recognize TransformerEngineBaseModule but unintentionally omit LinearAttentionBase.

For now, as discussed offline, could you please document the minimal TE lifecycle contract being implemented here ?

return True


def _gdn2_supported_arch() -> bool:

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.

nit: Any reason this check does not exist for GDN and only GDN-2 tests ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

GDN-2 doesn't have a cu-tile backend, only FROST engine is supported here, so blackwell+

return None


class LinearAttentionKernelAdapter(torch.nn.Module):

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.

Non-blocking follow-up: I like the private adapter as a thin shim, but _run() currently encodes several GDN/GDN2-specific assumptions: aligned Q/K/V token dimensions, identical Q/K shapes, equal Q/V head counts, and state heads derived from Q heads. These do not describe LA generally: GDP uses T Q/g rows but T ×num_householder K/V/beta rows, while KDA supports HK = H or HK = HV and uses HO = max(H, HV) for output/state heads.

Based on our offline discussion, I am okay deferring that generalization until KDA/GDP are added. At that point, I think these checks should move into the flavor-specific adapter rather than simply being removed or weakened globally, so GDN/GDN2 retain strict validation.
It would be helpful to leave a TODO or tracking issue recording that intended boundary.


Gated DeltaNet v2 replaces Gated DeltaNet's scalar gates with channel-wise
ones: ``g`` and ``beta`` carry one value per query/key channel and ``w`` one
value per value channel. The cuDNN frontend serves GDN-2 on Blackwell

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.

Incorrectly clubs 107 as Blackwell ?

if not torch.cuda.is_available():
return False
major, minor = torch.cuda.get_device_capability()
return (major, minor) in {(10, 0), (10, 1), (10, 2), (10, 3), (10, 7)}

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.

101, 102 ?



_GDN2_OP_AVAILABLE = _gdn2_op_available()
if os.getenv("NVTE_GDN2_TEST_REQUIRED", "0") == "1" and not _GDN2_OP_AVAILABLE:

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.

I'm unsure, but, could required mode also fail when the GPU architecture is unsupported? Currently it checks only whether the op/runtime imports; requires_gdn2 can then skip every numerical test on the wrong GPU, allowing the required CI command to pass without exercising GDN2. MAybe use a shared condition such as _GDN2_SUPPORTED = _GDN2_OP_AVAILABLE and _gdn2_supported_arch() for both the required-mode failure and the skip marker.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We run the CI with NVTE_GDN2_TEST_REQUIRED=1 and the _GDN2_OP_AVAILABLE checks GDN support. Later, _gdn2_supported_arch skips this test on unsupported architectures. So we will only run this test on supported hardware and skip otherwise.

Signed-off-by: Kirthi Shankar Sivamani <ksivamani@nvidia.com>
Signed-off-by: Kirthi Shankar Sivamani <ksivamani@nvidia.com>
@ksivaman

Copy link
Copy Markdown
Member Author

/te-ci pytorch L0

Comment on lines +159 to +160
value per value channel. The cuDNN frontend serves GDN-2 on Blackwell+
(SM100/SM103/SM107) only.

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.

P2 Architecture Support Is Overstated

Describing support as “Blackwell+” implies compatibility with architectures beyond Blackwell, but the same sentence limits the available engine to SM100, SM103, and SM107. This may lead users of later architectures to expect GDN2 to work when that support is not documented.

Suggested change
value per value channel. The cuDNN frontend serves GDN-2 on Blackwell+
(SM100/SM103/SM107) only.
value per value channel. The cuDNN frontend serves GDN-2 on Blackwell
(SM100/SM103/SM107) only.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants