You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[executorch][cuda] Converted convolutions follow the output layout the graph recorded - #25088
torch.export runs with cuDNN off and records a contiguous output for convolutions with a channels-last input, while ATen's CUDA convolution returns channels-last. The router refused calls whose recorded layout differed from ATen's, which excluded every channels-last-input convolution exported on CUDA.
triton::convolution takes an optional trailing output_strides. The fake implementation and the real allocation both get the output layout from out_shape_and_stride, which returns these strides when given and rejects non-dense ones. The router passes the node's recorded strides and refuses only non-dense ones, with the reason. worth_routing admits only measured (input, weight, output) memory-format combinations. Channels-last input with contiguous output is added where it was measured significantly faster than Inductor followed by contiguous(): the implicit GEMM at the 224 boundary corners in four precisions (895 of 896 significant), and the direct stencil from 12544 input elements (all 190 measured cases). The benchmarks gain this layout (--layout cl_to_nchw, --suite layouts).
test_conv_binding.py covers explicit strides, the dense check and the fake op; test_conv_routing.py routes CUDA-exported channels-last calls with the recorded strides and checks dense, non-dense and resized layouts and both templates' layout gates; the template tests write every dense output order.
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"
meta-claBot
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
Nov 14, 2026
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
CLA SignedThis label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.meta-exported
1 participant
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.
Stack from ghstack (oldest at bottom):
torch.export runs with cuDNN off and records a contiguous output for convolutions with a channels-last input, while ATen's CUDA convolution returns channels-last. The router refused calls whose recorded layout differed from ATen's, which excluded every channels-last-input convolution exported on CUDA.
triton::convolutiontakes an optional trailingoutput_strides. The fake implementation and the real allocation both get the output layout fromout_shape_and_stride, which returns these strides when given and rejects non-dense ones. The router passes the node's recorded strides and refuses only non-dense ones, with the reason.worth_routingadmits only measured (input, weight, output) memory-format combinations. Channels-last input with contiguous output is added where it was measured significantly faster than Inductor followed bycontiguous(): the implicit GEMM at the 224 boundary corners in four precisions (895 of 896 significant), and the direct stencil from 12544 input elements (all 190 measured cases). The benchmarks gain this layout (--layout cl_to_nchw,--suite layouts).test_conv_binding.pycovers explicit strides, the dense check and the fake op;test_conv_routing.pyroutes CUDA-exported channels-last calls with the recorded strides and checks dense, non-dense and resized layouts and both templates' layout gates; the template tests write every dense output order.This diff was authored with Claude Code.
Differential Revision: D129779886
NOTE FOR REVIEWERS: This PR has internal Meta-specific changes or comments, please review them on Phabricator!