Skip to content

Optionally pad QK/V for better kernel selection - #3339

Open
janEbert wants to merge 31 commits into
NVIDIA:mainfrom
janEbert:optional-mla-pad
Open

janEbert wants to merge 31 commits into
NVIDIA:mainfrom
janEbert:optional-mla-pad

Conversation

@janEbert

Copy link
Copy Markdown

Description

While support for native QKV shapes has been added, some MLA kernels
still benefit from having QKV padded to the same head dimension. Since
it's not easy to automate this decision, we probe
get_attention_backend twice with and without padding to figure out
which version selects the better kernel.

If padding results in a better kernel than not padding, we pad;
otherwise, Q, K, and V stay native.

Ref NVIDIA/Megatron-LM#6240, ref NVIDIA/Megatron-LM#6241.

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

Please list the changes introduced in this PR:

  • Automate MLA padding-related kernel selection
  • Add corresponding tests

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

@janEbert
janEbert requested a review from cyanguwa as a code owner August 10, 2026 22:47
@github-actions github-actions Bot added the community-contribution PRs from external contributor outside the core maintainers, representing community-driven work. label Aug 10, 2026
@greptile-apps

greptile-apps Bot commented Aug 10, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The changes since the previous review appear safe to merge; no new blocking issue was found.

Summary

The PR compares backend choices with native and padded head widths, then pads Q/K/V only when padding improves the choice. It trims attention output back to the original value width.

  • Attention pads unequal query/key and value widths only when it improves backend choice.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Native Q/K/V widths] --> B[Compare native and padded backend choices]
    B --> C{Does padding improve the choice?}
    C -->|Yes| D[Pad Q/K/V]
    C -->|No| E[Keep native widths]
    D --> F[Run selected attention backend]
    E --> F
    F --> G[Trim output if padded]
Loading

Reviews (12) · Last reviewed commit: "Improve cache clear usability" · Reviewed by Greptile

Comment thread tests/pytorch/attention/test_dpa_mla_qkv_head_dim_pad.py Outdated
Comment thread tests/pytorch/attention/test_dpa_mla_qkv_head_dim_pad.py Outdated
Comment thread tests/pytorch/attention/test_dpa_mla_qkv_head_dim_pad.py Outdated
@janEbert

Copy link
Copy Markdown
Author

PTAL.

@janEbert

Copy link
Copy Markdown
Author

Hey, friendly ping.

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

Please address the remaining couple of comments, and I'll start the CI. Thanks!

Comment thread transformer_engine/pytorch/attention/dot_product_attention/utils.py Outdated
Comment thread transformer_engine/pytorch/attention/dot_product_attention/utils.py Outdated
return None

if qkv_head_pad:
attn_out = _trim_output(attn_out, num_attention_heads, head_dim_qk, orig_head_dim_v)

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.

Would _trim_output(attn_out, num_attention_heads, head_dim_v, orig_head_dim_v) read a bit better, even though head_dim_qk = head_dim_v at the point?

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.

You might also need to be careful when attn_out is a Tuple for example with return_max_logit=True. There might be some logic needed to hitting that path. Thanks.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

For the former, I actually deliberately used qk to highlight that fact, but I'm fine with changing it to head_dim_v.

For the latter; thanks a lot! I didn't catch that because I was only looking at the type hints, which appear to be outdated. I'll update it as well if you don't mind. :)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Would you like tests to be added for the return_max_logit=True case as well?

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 think we can leave the type hints alone in backends.py. Currently TE doesn't have any mypy, pyright, or pytype checks anywhere - maybe something we should do in the future, and there's a lot more places to change when we do. :)

I think it's ok without the specific tests for return_max_logit=True. That's just "one of" the peripheral features that could or could not be affected when combined with the padding/backend reselection. If you like, you can add this flag to one of the mla tests you added (just by adding a kwarg to one of the configs in model_configs_mla).

While support for native QKV shapes has been added, some MLA kernels
still benefit from having QKV padded to the same head dimension. Since
it's not easy to automate this decision, we probe
`get_attention_backend` twice with and without padding to figure out
which version selects the better kernel.

If padding results in a better kernel than not padding, we pad;
otherwise, Q, K, and V stay native.

Signed-off-by: janEbert <janpabloe@nvidia.com>
Signed-off-by: janEbert <janpabloe@nvidia.com>
Signed-off-by: janEbert <janpabloe@nvidia.com>
Signed-off-by: janEbert <janpabloe@nvidia.com>
Signed-off-by: janEbert <janpabloe@nvidia.com>
Signed-off-by: janEbert <janpabloe@nvidia.com>
Signed-off-by: janEbert <janpabloe@nvidia.com>
Signed-off-by: janEbert <janpabloe@nvidia.com>
Signed-off-by: janEbert <janpabloe@nvidia.com>
Signed-off-by: janEbert <janpabloe@nvidia.com>
Signed-off-by: janEbert <janpabloe@nvidia.com>
Signed-off-by: janEbert <janpabloe@nvidia.com>
Signed-off-by: janEbert <janpabloe@nvidia.com>
Signed-off-by: janEbert <janpabloe@nvidia.com>
Signed-off-by: janEbert <janpabloe@nvidia.com>
It could be that all `native_use_*_attention` values are False, so this
needs to be handled.

Signed-off-by: janEbert <janpabloe@nvidia.com>
Signed-off-by: janEbert <janpabloe@nvidia.com>
Improve variable names along the way.

Signed-off-by: janEbert <janpabloe@nvidia.com>
@janEbert

Copy link
Copy Markdown
Author

I'm sorry for the late reply; doesn't make it easier to keep this in your head, for sure.

Comment thread transformer_engine/pytorch/attention/dot_product_attention/utils.py
Comment thread tests/pytorch/attention/test_attention.py Outdated
@cyanguwa cyanguwa added the 2.21 label Oct 12, 2026
Signed-off-by: janEbert <janpabloe@nvidia.com>
Comment thread transformer_engine/pytorch/attention/dot_product_attention/utils.py Outdated
Signed-off-by: janEbert <janpabloe@nvidia.com>
quantizers=None,
fp8_output: bool = False,
) -> torch.Tensor:
) -> Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]:

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.

How about this to prevent it from going stale - we may have more output tensors as more features are getting added.

Union[torch.Tensor, Tuple[torch.Tensor, ...]]

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I would argue it's good if it can go stale – in theory, a type checker should complain for all locations where a new n-tuple isn't correctly handled.
WDYT? Still change?

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.

See comment above. I think we can remove the changes you made, for now.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I reverted the varlength tuple change, if that is what you meant. If it's not, then I'd still argue to keep the type hint updates in some form (even if in a new PR). Even if it's not used by any static analysis tooling, it's extremely helpful just for human code reading.

Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
Comment thread tests/pytorch/attention/test_attention.py Outdated
@janEbert

Copy link
Copy Markdown
Author

I've also been fighting with the caching. It's extremely difficult due to the various interactions. Since you seemed to have started working on it, would you like to take it over?

The problem I've found is that, on the one hand, the _attention_backends variable is modified in forward after and possibly due to the results of should_pad_qkv_head_dim. However, we also want to force a cache refresh in case the backend data changes. Importantly, _attention_backends can be modified from the outside (e.g., other places in this repo also do that) and I think we also need to observe the different _THD_POLICY_BACKEND_ENV_VARS envvars as well in terms of cache invalidation.

Also add batch size config.

Signed-off-by: janEbert <janpabloe@nvidia.com>
Signed-off-by: janEbert <janpabloe@nvidia.com>
@greptile-apps

greptile-apps Bot commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Want your agent to iterate on Greptile's feedback? Try greploops.

janEbert and others added 3 commits October 14, 2026 19:13
This reverts commit 4029149.

Signed-off-by: janEbert <janpabloe@nvidia.com>
Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
@cyanguwa

Copy link
Copy Markdown
Collaborator

@janEbert can you take a look at my recent changes and see if they follow your original logic? Thanks.

@cyanguwa

Copy link
Copy Markdown
Collaborator

/te-ci pytorch L0 L1 L3

Comment thread tests/pytorch/attention/test_attention.py Outdated
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
@janEbert

Copy link
Copy Markdown
Author

I believe there is one case in which padding is activated even though it shouldn't be, but it may never be possible in the current state:

With native FlashAttention available and selected, padded FlashAttention not selected, but padded FusedAttention selected. In that case, we do pad, even though native FlashAttention would already be the best choice.

@janEbert

janEbert commented Oct 20, 2026 •

Copy link
Copy Markdown
Author

/te-ci pytorch L0 L1 L3

Too bad, doesn't work. Guess I'd have to be a member of a team for this repo. :)

Comment on lines +2837 to +2838
if _attention_backends["backend_selection_requires_update"]:
dpa_utils.clear_should_pad_qkv_head_dim_cache()

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I added another commit to allow passing an invalidate_cache boolean as an optional argument to should_pad_qkv_head_dim (in this case invalidate_cache=_attention_backends["backend_selection_requires_update"]). Then we can call the cache clear inside the function, which may be better in terms of user-facing visibility and API. Adjusted the test accordingly.

If you don't like the change, feel free to revert it.

Signed-off-by: janEbert <janpabloe@nvidia.com>
@cyanguwa cyanguwa added 2.22 and removed 2.21 labels Oct 23, 2026

This branch has not been deployed

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

Labels

2.22 attention community-contribution PRs from external contributor outside the core maintainers, representing community-driven work.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants