Repository navigation
Support 3-D convolution in the portable convolution kernel - #24460
Merged
Merged
Conversation
## What is wrong today A model with `torch.nn.Conv3d` lowers without an error but fails at run time on CPU, for example with XNNPACK: ``` Check failed (in.dim() == 3 || in.dim() == 4): Expect input tensor to be 3-D or 4-D, but got, 5. ``` XNNPACK does not take 3-D or bfloat16 convolutions, so they run on the portable convolution kernel, which only supported 1-D and 2-D. This blocks vision encoders with a `Conv3d` patch embedding, such as Qwen2-VL and Qwen2.5-VL. It is the failure in #11704. ## What this change does The portable convolution kernel now runs 3-D convolutions, regular and transposed. 1-D and 2-D convolutions run as 3-D ones with extra dims of size 1 and add up their terms in the same order as before, so their results stay the same (except that, with fused multiply-add, a result of -0 can now be +0, as in PyTorch). The input and output may now have different dim orders, because `torch.export` gives a `Conv3d` with a channels-last input a contiguous output. The backend test suite no longer skips 3-D convolutions. It also fixes older bugs in the argument checks, which affect 1-D and 2-D too: - A bias of the wrong length was read past its end (missing parentheses), and a Bool bias crashed the kernel. - `groups = 0` divided by zero, and a huge `groups` could overflow in the bias check. - A huge padding or dilation, or an output size too large for the 32-bit tensor sizes, let a call that should fail run. Stride, padding and dilation must now fit in 32 bits. - Like PyTorch, the checks now reject a kernel dim of 0, a regular convolution's kernel larger than the padded input, and an empty spatial dim unless the batch or channel dim is empty too. ## Testing - New tests cover grouped regular and transposed 3-D convolutions with contiguous, channels-last and mixed layouts, and the checks above. All but one fail without this change; that one checks that an empty batch or channel dim still works. - The portable kernel tests pass with AddressSanitizer and UndefinedBehaviorSanitizer on Linux Arm64. - The Cortex-M `conv3d` test, now with several channels, a 2x3x3 kernel, stride and padding, no longer expects a failure and passes in CI on the Arm simulator. - A `Conv3d` patch embedding lowered with XNNPACK, and random convolutions on the portable kernel, match eager PyTorch in float32 and bfloat16. - Speed against main on Arm64 and x86-64: regular 1-D and 2-D convolutions are 1.5 to 13 times faster with GCC and with Clang at `-Os`, and 18 percent faster to 11 percent slower with Clang at `-O2` and `-O3`. Transposed ones are 5 percent faster to 17 percent slower. - Code size for a Cortex-M55 (Arm GNU toolchain 15.2): `op_convolution.o` grows from 32,484 to 33,263 bytes at `-Os` and from 48,477 to 61,457 at `-O3`. `kernel_ops_util.o`, which holds the argument checks, grows from 15,746 to 17,743 bytes at `-Os` and from 25,932 to 28,979 at `-O3`. ## Notes - Depends on #24380. Without it, a static int8 `Conv3d` lowered with XNNPACK returns wrong values with no error, or fails to load, and the backend test suite's static int8 XNNPACK `Conv3d` cases fail. Please merge #24380 first or together with this change. - An earlier version of 3-D support was reverted, see #19977. (cherry picked from commit 76efad5)
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/24460
Note: Links to docs will display an error until the docs builds have been completed. ✅ You can merge normally! (2 Unrelated Failures)As of commit 929ffdc with merge base 4db778e ( BROKEN TRUNK - The following jobs failed but were present on the merge base:👉 Rebase onto the `viable/strict` branch to avoid these failures
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
This was referenced Nov 2, 2026
JacobSzwejbka
approved these changes
Nov 3, 2026
This branch was previously deployed
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.
Merge after #24445. It does not depend on it to build, but #24445 brings the XNNPACK fix for statically quantized 3-D convolutions, and without it the backend test suite would report those cases as failing once this pick removes the 3-D skip.
What is wrong today
A model with
torch.nn.Conv3dlowers without an error but fails at run time on CPU, for example with XNNPACK:XNNPACK does not take 3-D or bfloat16 convolutions, so they run on the portable convolution kernel, which only supported 1-D and 2-D. This blocks vision encoders with a
Conv3dpatch embedding, such as Qwen2-VL and Qwen2.5-VL. It is the failure in #11704.What this change does
The portable convolution kernel now runs 3-D convolutions, regular and transposed. 1-D and 2-D convolutions run as 3-D ones with extra dims of size 1 and add up their terms in the same order as before, so their results stay the same (except that, with fused multiply-add, a result of -0 can now be +0, as in PyTorch). The input and output may now have different dim orders, because
torch.exportgives aConv3dwith a channels-last input a contiguous output. The backend test suite no longer skips 3-D convolutions.It also fixes older bugs in the argument checks, which affect 1-D and 2-D too:
groups = 0divided by zero, and a hugegroupscould overflow in the bias check.Testing
conv3dtest, now with several channels, a 2x3x3 kernel, stride and padding, no longer expects a failure and passes in CI on the Arm simulator.Conv3dpatch embedding lowered with XNNPACK, and random convolutions on the portable kernel, match eager PyTorch in float32 and bfloat16.-Os, and 18 percent faster to 11 percent slower with Clang at-O2and-O3. Transposed ones are 5 percent faster to 17 percent slower.op_convolution.ogrows from 32,484 to 33,263 bytes at-Osand from 48,477 to 61,457 at-O3.kernel_ops_util.o, which holds the argument checks, grows from 15,746 to 17,743 bytes at-Osand from 25,932 to 28,979 at-O3.Notes
Conv3dlowered with XNNPACK returns wrong values with no error, or fails to load, and the backend test suite's static int8 XNNPACKConv3dcases fail. Please merge Keep ops above 6 dims out of XNNPACK and fix quantized ops it leaves out #24380 first or together with this change.