Skip to content

Add fuse_attention pass for torch.onnx SDPA graphs - #321

Open
take-cheeze wants to merge 1 commit into
onnx:mainfrom
onnxsim:claude/fuse-attention-torch-onnx-viw15m
Open

Add fuse_attention pass for torch.onnx SDPA graphs#321
take-cheeze wants to merge 1 commit into
onnx:mainfrom
onnxsim:claude/fuse-attention-torch-onnx-viw15m

Conversation

@take-cheeze

Copy link
Copy Markdown
Member

Fuse the sub-graph that torch.onnx.export (the TorchScript exporter) emits for scaled_dot_product_attention into a single ONNX Attention operator (opset 23+).

The exported pattern scales Q and the transposed K by sqrt(scale), multiplies them, optionally adds an attention mask, applies Softmax over the last axis and multiplies by V. Anchored on the final MatMul(Softmax(...), V), the pass recognizes this shape and rewrites it to Attention(Q, K, V[, attn_mask]):

  • explicit scale= (constant sqrt(scale) factors) -> scale attribute set to the product of the two factors
  • default scale (the 1/sqrt(head_size) sub-graph torch derives from Shape(Q)) -> scale left implicit, matching Attention's default
  • additive / causal masks -> fed through as attn_mask

Guarded on opset >= 23 (where Attention exists) so lower-opset models are left untouched. Tests cover hand-built graphs mirroring the exporter output plus graphs produced by the real torch.onnx exporter.

Claude-Session: https://claude.ai/code/session_01CHJoCKJ1p5YFm2ZMwdwaWV

Fuse the sub-graph that `torch.onnx.export` (the TorchScript exporter)
emits for `scaled_dot_product_attention` into a single ONNX `Attention`
operator (opset 23+).

The exported pattern scales Q and the transposed K by `sqrt(scale)`,
multiplies them, optionally adds an attention mask, applies Softmax over
the last axis and multiplies by V. Anchored on the final
`MatMul(Softmax(...), V)`, the pass recognizes this shape and rewrites it
to `Attention(Q, K, V[, attn_mask])`:

- explicit `scale=` (constant sqrt(scale) factors) -> `scale` attribute
  set to the product of the two factors
- default scale (the `1/sqrt(head_size)` sub-graph torch derives from
  `Shape(Q)`) -> `scale` left implicit, matching Attention's default
- additive / causal masks -> fed through as `attn_mask`

Guarded on opset >= 23 (where `Attention` exists) so lower-opset models
are left untouched. Tests cover hand-built graphs mirroring the exporter
output plus graphs produced by the real torch.onnx exporter.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CHJoCKJ1p5YFm2ZMwdwaWV
Signed-off-by: take-cheeze <takechi101010@gmail.com>
@take-cheeze
take-cheeze requested review from a team as code owners July 26, 2026 03:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants