[ET-VK] Fix out-of-range broadcast size calculation for 0-dim tensors - #22332
Open
msluszniak wants to merge 1 commit into
Open
[ET-VK] Fix out-of-range broadcast size calculation for 0-dim tensors#22332msluszniak wants to merge 1 commit into
msluszniak wants to merge 1 commit into
Conversation
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.
🔗 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.
|
This PR needs a
|
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #22331.
calculate_broadcasted_output_size()guards its loop withi >= -out_sizes.size(). That issize_tarithmetic, so when both operands are 0-dimensional the bound evaluates to0,ipromotes toSIZE_MAX, the guard stays true, and the body runsout_sizes.at(0 - 1)on an empty vector, throwingstd::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() == 2the bound isSIZE_MAX - 1, soi = -1, -2pass andi = -3fails, 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
encodemethod (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):
x.max() - (x.max() - 1.0), 0-dim outputx - x.max(), 0-dim broadcast to rank 1encodetest_vulkan_backend_binary_op_zero_dimcovers the 0-dim case.