Repository navigation
Add a portable kernel for antialiased bicubic resize - #24444
Closed
pytorchbot wants to merge 1 commit into
Closed
pytorchbot wants to merge 1 commit into
pytorchbot wants to merge 1 commit into
Conversation
`to_edge` cannot lower `F.interpolate(x, mode="bicubic", antialias=True)` today. It exports to `aten._upsample_bicubic2d_aa`, which is not a core ATen op, so `to_edge` stops with: ``` SpecViolationError: Operator torch._ops.aten._upsample_bicubic2d_aa.default is not in Core ATen opset ``` ExecuTorch also has no kernel for it. ## What this change does It adds a portable kernel for `_upsample_bicubic2d_aa.out` and lists the op as an exception in the edge verifier, as the antialiased bilinear resize does. Like ATen's CPU kernel, it uses the Keys cubic filter (a = -0.5), widened when shrinking, resizes the width, then the height, and copies a dim that keeps its size. float16 and bfloat16, which ATen's CPU kernel lacks, are computed in float32 and rounded once. uint8 follows ATen's fixed-point path: 16-bit integer weights, and each pass rounds and clamps. Other integer types fail in the kernel, as they do in ATen. Between passes it keeps only the rows one output row reads, so shrinking 1080x1920 to 224x224 needs about 95 KB of temporary memory (43 KB for uint8). It rejects scales `F.interpolate` never produces: too small for the input, or (uint8 only) with weights too large for 16 bits. Where ATen's generic CPU path is wrong (contiguous input, output width 1, changing height; [PyTorch issue 200568](pytorch/pytorch#200568)), it differs from eager on purpose. The shared upsample helper now ignores a non-positive scale, as ATen does; of the other upsample kernels, only antialiased bilinear can pass one. A stale llava comment is updated, and the Arm all-ops test marks the kernel as needing a recipe. Like several portable kernels, it has no experimental CPU backend route yet. ## Testing - New kernel tests check against ATen: shrinking, `align_corners`, scales, windows past the input, kept dims, both layouts, a batch, all float types, uint8 bit for bit, a dynamic output, running out of temporary memory, and error cases. Each case catches a bug that no other case catches. - The `to_edge` test compares static and dynamic programs (both layouts) with eager in float32 and, bit for bit, in uint8. It fails without the kernel or the verifier exception. - Outside the suite, a random sweep matched ATen's uint8 results exactly on x86 and Arm, on both its vectorized and generic paths; float32 within 7e-6 for unit-scale inputs, half types within one unit in the last place. - With XNNPACK, the resize stays outside the delegate. On one laptop thread, shrinking a contiguous 1080x1920 input to 224x224 takes about 7 ms (12 ms channels last). (cherry picked from commit a5476a5)
pytorchbot
requested review from
JacobSzwejbka and
larryliu0820
as code owners
November 2, 2026 16:49
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/24444
Note: Links to docs will display an error until the docs builds have been completed. ⏳ No Failures, 349 PendingAs of commit e1d0517 with merge base 4db778e ( This comment was automatically generated by Dr. CI and updates every 15 minutes. |
Contributor
This branch was successfully 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.
to_edgecannot lowerF.interpolate(x, mode="bicubic", antialias=True)today. It exports toaten._upsample_bicubic2d_aa, which is not a core ATen op, soto_edgestops with:ExecuTorch also has no kernel for it.
What this change does
It adds a portable kernel for
_upsample_bicubic2d_aa.outand lists the op as an exception in the edge verifier, as the antialiased bilinear resize does.Like ATen's CPU kernel, it uses the Keys cubic filter (a = -0.5), widened when shrinking, resizes the width, then the height, and copies a dim that keeps its size. float16 and bfloat16, which ATen's CPU kernel lacks, are computed in float32 and rounded once. uint8 follows ATen's fixed-point path: 16-bit integer weights, and each pass rounds and clamps. Other integer types fail in the kernel, as they do in ATen.
Between passes it keeps only the rows one output row reads, so shrinking 1080x1920 to 224x224 needs about 95 KB of temporary memory (43 KB for uint8). It rejects scales
F.interpolatenever produces: too small for the input, or (uint8 only) with weights too large for 16 bits. Where ATen's generic CPU path is wrong (contiguous input, output width 1, changing height; PyTorch issue 200568), it differs from eager on purpose.The shared upsample helper now ignores a non-positive scale, as ATen does; of the other upsample kernels, only antialiased bilinear can pass one. A stale llava comment is updated, and the Arm all-ops test marks the kernel as needing a recipe. Like several portable kernels, it has no experimental CPU backend route yet.
Testing
align_corners, scales, windows past the input, kept dims, both layouts, a batch, all float types, uint8 bit for bit, a dynamic output, running out of temporary memory, and error cases. Each case catches a bug that no other case catches.to_edgetest compares static and dynamic programs (both layouts) with eager in float32 and, bit for bit, in uint8. It fails without the kernel or the verifier exception.cc @digantdesai @freddan80 @per @zingo @oscarandersson8218 @mansnils @Sebastian-Larsson @robell @rascani