[ET-VK] Do not partition constant_pad_nd with a symbolic pad - #22399
Open
msluszniak wants to merge 1 commit into
Open
[ET-VK] Do not partition constant_pad_nd with a symbolic pad#22399msluszniak wants to merge 1 commit into
msluszniak wants to merge 1 commit into
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/22399
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
Sep 1, 2026
Backport of pytorch/executorch#22399. Two op registrations advertise support the runtime does not have, so a graph containing either lowers cleanly and then aborts at execute time. constant_pad_nd: a symbolic pad list is serialized as a VALUELIST, and Pad.cpp reads it with get_int_list(), raising "Expected value to have type IntList, got VALUELIST instead". add_constant_pad_nd_node() also bakes the pad amounts into a params buffer at build time, so a pad derived from a dynamic dim would be stale even if the list were read symbolically; decline both cases rather than trade an abort for a wrong result. _native_batch_norm_legit_no_training: add_native_batch_norm_node() asserts in_sizes.size() == 4, so any conv1d model (rank-3 activations) aborts with "BatchNorm only support 4d tensor". Both now fall back instead of aborting. Found with the Supertonic TTS model, whose text encoder hits the first (VITS relative-attention pads are derived from the sequence length) and whose vocoder hits the second.
msluszniak
added a commit
to software-mansion-labs/executorch
that referenced
this pull request
Sep 1, 2026
Backport of pytorch/executorch#22399. get_val_or_inf() in UnaryOp.cpp reads each clamp bound with extract_scalar<float>() when the node is BUILT and bakes the result into the dispatch, so a bound derived from a dynamic dim is never refreshed and the op silently computes against a stale limit. Worst when clamp is applied to index tensors, where a wrong limit reorders or drops data downstream. Supertonic on S26 Ultra (Adreno 840), vs a CPU reference that XNNPACK reproduces at cosine 1.000000: vocoder 0.016757 -> 0.999977 vector_estimator 0.994432 -> 0.999994 hardtanh, hardshrink and leaky_relu share the same build-time path.
This was referenced Sep 1, 2026
A pad amount derived from a dynamic dimension is serialized as a VALUELIST of Int/SymInt, and Pad.cpp reads the list with get_int_list(), which requires a literal IntList. The partitioner claims the node regardless, so the model lowers and then aborts at prepack: Exception raised from toIntList at .../graph/containers/Value.h:272: (isIntList()) is false! Expected value to have type IntList, got VALUELIST This is reachable from ordinary code. Any model that pads a dynamic sequence up to the static length its LSTM wants hits it, which is how kokoro's synthesizer fails: `F.pad(x, (0, 0, 0, target - seq_len))`. Supporting it properly is more than swapping in extract_int_or_symint_list(), the way Split.cpp, View.cpp and Expand.cpp read their symbolic lists. add_constant_pad_nd_node() folds the amounts into a per-dim offset and bakes that into a params buffer at build time, so the dispatch would use stale offsets even if the list were read symbolically; the buffer has to be refreshed on resize first. Decline the node until then, so it falls back rather than aborting. The existing test_vulkan_backend_constant_pad_nd pads by a literal (1, 2, 3, 4, 5, 6), so no test covered a symbolic pad. The new case aborts on main and falls back cleanly with this change.
msluszniak
force-pushed
the
ms/vulkan-partitioner-guards
branch
from
September 3, 2026 07:19
6da6af3 to
77c1a8c
Compare
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.
Summary
A pad amount derived from a dynamic dimension is serialized as a
VALUELISTof Int/SymInt, andPad.cppreads the list withget_int_list(), which requires a literalIntList. The partitioner claims the node regardless, so the model lowers and then aborts at prepack:This is reachable from ordinary code. Any model that pads a dynamic sequence up to the static length its LSTM wants hits it, which is how kokoro's synthesizer fails:
Why not just read the list symbolically
Split.cpp,View.cppandExpand.cppall handle a symbolic list withextract_int_or_symint_list(), andPad.cppwas simply missed. Swapping the extractor in is not sufficient on its own, though:add_constant_pad_nd_node()folds the amounts into a per-dim offset and bakes that into a params buffer at build time, so the dispatch would use stale offsets even if the list were read symbolically. Refreshing that buffer on resize is the real fix and is left for a follow-up. Until then this declines the node so it falls back instead of aborting.Test plan
test_vulkan_backend_constant_pad_ndpads by a literal(1, 2, 3, 4, 5, 6), so no test covered a symbolic pad.test_vulkan_backend_constant_pad_nd_symbolic_padaborts on main and falls back cleanly with this change.Note on scope
This PR previously also guarded
clamp/hardtanhand_native_batch_norm_legit_no_training.clampandhardtanhviaadd_dynamic_clamp_node, which is strictly better than declining, and keeping the guard alongside it would decline nodes that now work.hardshrinkandleaky_relustill read their bounds at build time throughget_val_or_inf(), but a symboliclambdaornegative_slopeis a hyperparameter no real model produces, so that is left alone rather than guarded.Merges cleanly with #22481.