Skip to content

Cortex-M: decompose SDPA with score scaling after matmul - #22892

Open
amacharla15 wants to merge 1 commit into
pytorch:mainfrom
amacharla15:issue-21943-scale-sink
Open

amacharla15 wants to merge 1 commit into
pytorch:mainfrom
amacharla15:issue-21943-scale-sink

Conversation

@amacharla15

@amacharla15 amacharla15 commented Sep 17, 2026 •

Copy link
Copy Markdown

Summary

Decompose eligible aten.scaled_dot_product_attention directly in the
Cortex-M transform_for_annotation pipeline.

The Cortex-M decomposition is:

scores = matmul(query, key.transpose(-2, -1))
scores = scores * scale
attn = softmax(scores, dim=-1)
output = matmul(attn, value)

The existing MatmulToBmmPass then converts the matmuls to BMMs.

This replaces the previous approach that rewrote the output of
DecomposeSDPAWithRegularSoftmaxPass. That Arm decomposition is not part of
the Cortex-M pipeline, so the previous pass did not run in the real flow.

Keeping the attention scale as a single MUL on the score tensor allows the
stock CortexMQuantizer to produce proportional qparams around that MUL,
making it suitable for later folding without adding Cortex-M-specific qspec
logic to the quantizer.

The decomposition is intentionally limited to fp32, unmasked, non-causal,
zero-dropout, non-GQA SDPA with static, non-empty shapes of rank 3 or higher
and matching leading dimensions. Unsupported forms are left unchanged.

Addresses the scale/decomposition part of #21943.

Tests

Added a full SDPA operator test starting from
torch.nn.functional.scaled_dot_product_attention, with no manual SDPA
decomposition.

The tests verify that:

  • raw SDPA is removed by the Cortex-M transform-for-annotation pipeline;
  • the two matmuls become BMMs;
  • exactly one scale MUL and one softmax remain, and the decomposed graph
    matches eager SDPA;
  • the MUL sits between a dequantize and quantize with
    out_scale ~= in_scale * scale and equal zero points, so it can be folded
    later;
  • unsupported SDPA forms, including dynamic shapes, are left unchanged.

The SDPA dialect cases are xfailed because no lowering pass folds the scale
MUL yet, using the existing xfails mechanism of parametrize with its
default strict behavior.

nn.MultiheadAttention(need_weights=False) regresses with this change. On
main it lowers with the attention left in fp32. With this change its
attention BMMs are quantized, and a BMM then gets an int8 input together with
the int32 output of a retraced folded linear, the separate issue from #21943.
That case is also xfailed.

Local verification:

  • SDPA tests without implementation/FVP coverage: 19 passed, 5 xfailed,
    5 deselected;
  • existing BMM/matmul/softmax tests passed;
  • lintrunner passed;
  • full Cortex-M suite comparison introduced no new failures versus the parent
    commit.

FVP implementation tests were not run locally and are covered by the
Cortex-M CI job.

Copilot AI lite review requested due to automatic review settings September 17, 2026 02:05
@pytorch-bot

pytorch-bot Bot commented Sep 17, 2026 •

Copy link
Copy Markdown

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/22892

Note: Links to docs will display an error until the docs builds have been completed.

⏳ No Failures, 2 Pending

As of commit 6864d71 with merge base ed72896 (image):
💚 Looks good so far! There are no failures yet. 💚

This comment was automatically generated by Dr. CI and updates every 15 minutes.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Sep 17, 2026

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@amacharla15

Copy link
Copy Markdown
Author

@pytorchbot label "release notes: none"

@pytorch-bot pytorch-bot Bot added the release notes: none Do not include this in the release notes label Sep 17, 2026
@nil-is-all nil-is-all added partner: arm For backend delegation, kernels, demo, etc. from the 3rd-party partner, Arm module: quantization Issues related to quantization module: arm Issues related to arm backend labels Sep 17, 2026
@nil-is-all

Copy link
Copy Markdown
Contributor

Hi @AdrianLundell, CI looks good on this PR. Could you give a final review?

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

Thanks for the update, this is getting closer now! The new pass is targeting the decomposition from the Arm DecomposeSDPAWithRegularSoftmaxPass and then rewrites it, I see two things wrong with this:

  1. As currently written the pass will never do anything since DecomposeSDPAWithRegularSoftmaxPass is not in the Cortex-M pass pipeline.
  2. Rewriting the decomposition of one pass with another one is a bit convoluted, it would make more sense to me to reimplement the SDPA decomposition in a way which suits the Cortex-M backend better directly instead.

Please also add a full SDPA operator test with these changes to make sure the full flow makes sense, if there are more changes required to make them pass fully that is fine, just make sure that the intended change is happening (muls are annotated correctly for folding) and then xfail the tests with a comment about remaining work needed.

@executorch-triage executorch-triage Bot added the community: contribution PRs coming from community (excluding hardware partners) label Sep 22, 2026
@amacharla15
amacharla15 force-pushed the issue-21943-scale-sink branch from 6c88f64 to 05766a2 Compare September 23, 2026 04:24
Copilot AI review requested due to automatic review settings September 23, 2026 04:24

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@amacharla15

Copy link
Copy Markdown
Author

Thanks for the review @AdrianLundell. I updated the PR to match the points you raised.

  • You pointed out that the previous pass depended on DecomposeSDPAWithRegularSoftmaxPass, which is not part of the Cortex-M pipeline, so it never ran in the real flow. I removed that dependency and replaced the old rewrite pass with DecomposeSDPAPass, which runs directly in transform_for_annotation.

  • You also suggested decomposing SDPA directly in a Cortex-M-friendly form instead of rewriting another decomposition. The new pass lowers eligible SDPA directly to:

    matmul -> mul(scale) -> softmax -> matmul
    

    with the scale applied once to the scores. The existing MatmulToBmmPass then converts the supported matmuls to BMMs. Unsupported SDPA forms are left unchanged.

  • SDPA operator test: ops/test_sdpa.py now starts from F.scaled_dot_product_attention and runs through the Cortex-M flow without manually invoking any SDPA decomposition pass.

  • You also asked to make sure the intended MUL behavior is present for folding, and to xfail the remaining work if needed. The test verifies that the score MUL sits between DQ and Q with out_scale ~= in_scale * scale and equal zero points. The dialect cases that still need the MUL-folding pass are xfailed only on the specific expected failure message, so unrelated failures still fail normally.

One remaining issue: nn.MultiheadAttention(need_weights=False) lowers on main today with attention in float. With this change its attention BMMs become quantized, and lowering reaches the separate folded-linear retrace issue from #21943 (int8 vs int32).

@amacharla15 amacharla15 changed the title Cortex-M: move SDPA score scale after bmm Cortex-M: move SDPA score scale after bmmCortex-M: move SDPA score scale after bmm Sep 23, 2026
@amacharla15 amacharla15 changed the title Cortex-M: move SDPA score scale after bmmCortex-M: move SDPA score scale after bmm Cortex-M: decompose SDPA with score scaling after matmul Sep 23, 2026
Comment thread backends/cortex_m/test/ops/test_sdpa.py Outdated
}


def _run_with_known_failure(

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 re-use the existing xfail mechanism in the parametrize decorator instead.

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

Looks good overall to me now, just fix the tests to use the regular xfailing mechanism instead of a special function and it is an approve from my side. @rascani Do you have any input also?

The default SDPA decomposition splits the attention scale over query and
key, where the quantizer cannot give the scale muls proportional qparams.
Decompose SDPA before annotation with a single scale on the scores
instead, so the scale mul gets qparams that allow folding it.
Copilot AI review requested due to automatic review settings September 24, 2026 15:18
@amacharla15
amacharla15 force-pushed the issue-21943-scale-sink branch from 05766a2 to 6864d71 Compare September 24, 2026 15:18

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@amacharla15

Copy link
Copy Markdown
Author

Thanks @AdrianLundell , switched to the xfails mechanism in parametrize.

@rascani

rascani commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

This LGTM, I think I'd just ask that we follow-up with a fix for the nn.MultiheadAttention(need_weights=False) regression soon. @amacharla15 - let us know if you're planning on tackling that.

Thanks for this! I really appreciate your contribution.

@amacharla15

Copy link
Copy Markdown
Author

Thanks @rascani, really appreciate the review! Yes, I’d like to take the nn.MultiheadAttention(need_weights=False) follow-up.

@AdrianLundell, on #22796 you mentioned an upcoming prototype for changing how folded Q/DQ parameters are handled in the graph. Is that work available now, and should I base this follow-up on it rather than adding a separate Cortex-M-specific workaround?

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

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. community: contribution PRs coming from community (excluding hardware partners) module: arm Issues related to arm backend module: quantization Issues related to quantization partner: arm For backend delegation, kernels, demo, etc. from the 3rd-party partner, Arm release notes: none Do not include this in the release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants