Skip to content

[ET-VK] Fix out-of-range broadcast size calculation for 0-dim tensors - #22332

Open
msluszniak wants to merge 1 commit into
pytorch:mainfrom
msluszniak:ms/vulkan-rank0-broadcast
Open

[ET-VK] Fix out-of-range broadcast size calculation for 0-dim tensors#22332
msluszniak wants to merge 1 commit into
pytorch:mainfrom
msluszniak:ms/vulkan-rank0-broadcast

Conversation

@msluszniak

Copy link
Copy Markdown
Contributor

Fixes #22331.

calculate_broadcasted_output_size() guards its loop with i >= -out_sizes.size(). That is size_t arithmetic, so when both operands are 0-dimensional the bound evaluates to 0, i promotes to SIZE_MAX, the guard stays true, and the body runs out_sizes.at(0 - 1) on an empty vector, throwing std::out_of_range.

check_binary_op_args() calls it during graph construction, so any binary op with a 0-dimensional output aborts at load rather than failing at execute time.

Non-empty outputs are unaffected and stay bit-identical: the same unsigned wraparound happens to compare correctly there. With size() == 2 the bound is SIZE_MAX - 1, so i = -1, -2 pass and i = -3 fails, exactly as intended. Only the empty case is broken. This holds the bound in a signed local so the loop is simply skipped.

Why it matters

Whisper's log-mel normalisation subtracts one scalar from another, so its whole encode method (mel preprocessor plus encoder) could not be loaded on Vulkan. That is not caused by the dynamic audio dimension (a static 30 s export fails identically) or by multi-method lowering (an encode-only .pte fails identically).

Verification

Snapdragon SM8850 (Adreno 840):

model before after
x.max() - (x.max() - 1.0), 0-dim output abort exact, max abs diff 0
x - x.max(), 0-dim broadcast to rank 1 ok exact, max abs diff 0
same arithmetic at rank 1 ok exact, max abs diff 0
Whisper-tiny encode abort at load runs, cosine 0.99998790 vs CPU

test_vulkan_backend_binary_op_zero_dim covers the 0-dim case.

calculate_broadcasted_output_size() guards its loop with
`i >= -out_sizes.size()`. That is size_t arithmetic: when both operands are
0-dimensional the bound evaluates to 0, `i` promotes to a huge unsigned value,
the guard stays true, and the body runs `out_sizes.at(size() - 1)` on an empty
vector, throwing std::out_of_range.

Any binary op whose output is 0-dimensional therefore aborts at graph build.
Whisper hits it in the log-mel normalisation, which makes its whole encode
method unloadable on Vulkan.

Hold the bound in a signed local so the loop is skipped when the output is
0-dimensional. Non-empty cases are unchanged: the previous unsigned wraparound
happened to compare correctly for them.
@msluszniak
msluszniak requested a review from SS-JIA as a code owner August 30, 2026 13:53
@pytorch-bot

pytorch-bot Bot commented Aug 30, 2026

Copy link
Copy Markdown

🔗 Helpful Links

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

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

⚠️ 15 Awaiting Approval

As of commit 7f484a7 with merge base c27baa8 (image):

AWAITING APPROVAL - The following workflows need approval before CI can run:

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 Aug 30, 2026
@github-actions

Copy link
Copy Markdown

This PR needs a release notes: label

If your change should be included in the release notes (i.e. would users of this library care about this change?), please use a label starting with release notes:. This helps us keep track and include your important work in the next release notes.

To add a label, you can comment to pytorchbot, for example
@pytorchbot label "release notes: none"

For more information, see
https://github.com/pytorch/pytorch/wiki/PyTorch-AutoLabel-Bot#why-categorize-for-release-notes-and-how-does-it-work.

msluszniak added a commit to software-mansion-labs/executorch that referenced this pull request Aug 30, 2026
calculate_broadcasted_output_size guards its loop with i >= -out_sizes.size(),
which is size_t arithmetic. With two 0-dimensional operands the bound is 0, i
promotes to a huge unsigned value and the body indexes an empty vector,
throwing std::out_of_range at graph build.

Whisper hits this in its log-mel normalisation, which makes its whole encode
method unloadable.

Upstream: pytorch/executorch#22331, pytorch/executorch#22332
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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ET-VK] Binary ops with a 0-dimensional output abort with std::out_of_range

2 participants