Resize PR 3: Run Resize on the Metal GPU - #2556
Open
czoli1976 wants to merge 1 commit into
Open
Conversation
This was referenced Aug 2, 2026
czoli1976
force-pushed
the
feature/resize-metal-kernel
branch
from
August 3, 2026 12:28
690e5af to
592639d
Compare
|
🔴 Bench vs main — 2 speed regression(s) · Reference: 2026-08-03 morning nightly run (0d old) · full report → run Speed — evaltime · prefill · decode
Improvements
|
| Δ | metric | device | main → PR |
|---|---|---|---|
| hey_snips_v1 load · 400ms |
cortex-a9 |
75 ms → 92 ms | |
| arm_ml_kws_cnn_m load · pass |
cortex-a9 |
84 ms → 103 ms | |
| hey_snips_v1 load+optimize · 400ms |
cortex-a9 |
145 ms → 174 ms | |
| arm_ml_kws_cnn_m load+optimize · pass |
cortex-a9 |
131 ms → 155 ms | |
| arm_ml_kws_cnn_m load+optimize · pass |
cortex-a7 |
117 ms → 134 ms | |
| arm_ml_kws_cnn_m load · pass |
cortex-a7 |
78 ms → 89 ms | |
| hey_snips_v1 load · 400ms |
cortex-a7 |
67 ms → 74 ms | |
| llama_3_2_3B_instruct_q40ef16_541 load+optimize · cuda |
jetson-orin-nx |
4.14 s → 4.53 s | |
| qwen3_1_7B_q40ef16_541 load+optimize · cuda |
jetson-orin-nx |
3.77 s → 4.01 s | |
| en_tdnn_15M RSS @ ready · 2600ms |
cortex-a55 |
111 MB → 117 MB | |
| arm_ml_kws_cnn_m load+optimize · pass |
cortex-a53 |
74 ms → 78 ms |
Resize had no Metal kernel, so every node round-tripped the tensor through the host in the middle of a GPU graph. A resample-one-axis kernel now consumes the same per-axis tap-and-weight plan the CPU op builds, which makes it independent of the interpolator; the plan is baked at translation time, so the node keeps only its data input and the scales/sizes TDim constant is dropped.
Collaborator
|
|
kali
force-pushed
the
feature/resize-metal-kernel
branch
from
August 6, 2026 17:57
592639d to
d23cd23
Compare
|
🔴 Bench vs main — 1 speed regression(s) · Reference: 2026-08-07 morning nightly run (0d old) · full report → run Speed — evaltime · prefill · decode
|
| Δ | metric | device | main → PR |
|---|---|---|---|
| arm_ml_kws_cnn_m load · pass |
cortex-a9 |
84 ms → 122 ms | |
| arm_ml_kws_cnn_m load+optimize · pass |
cortex-a9 |
130 ms → 179 ms | |
| arm_ml_kws_cnn_m load · pass |
cortex-a7 |
78 ms → 91 ms | |
| hey_snips_v1 load · 400ms |
cortex-a7 |
67 ms → 77 ms | |
| hey_snips_v1 load+optimize · 400ms |
cortex-a7 |
112 ms → 127 ms | |
| arm_ml_kws_cnn_m load+optimize · pass |
cortex-a7 |
118 ms → 133 ms | |
| arm_ml_kws_cnn_m load · pass |
cortex-a53 |
48 ms → 54 ms | |
| arm_ml_kws_cnn_m load+optimize · pass |
cortex-a53 |
73 ms → 81 ms |
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.
Resize had no Metal kernel, so in a GPU graph every node round-tripped its tensor through the host. This adds a resample-one-axis kernel that consumes the same per-axis tap/weight plan the CPU op builds, which makes one kernel enough for nearest, linear, cubic and their antialiased variants — they differ only in window size and weights.
Needed the
AxisPlanfrom #2554 and #2555; now that both are merged this is rebased onto main and stands alone as a single commit.Wiring
The plan depends only on shapes and attributes, so it is baked at translation time; the node then keeps just its data input. That is also why this is wired in
translate_noderather than throughregister_metal_op!: the macro rewires the same inputs, and Resize'sscales/sizesconstant is aTDim, whose datum type fails the device-dtype gate intry_make_metal_op— the node was rejected before any translator ran. Nodes with a symbolic shape or a non-constant scales input aren't translated and stay on CPU.Effect
u2netp (rembg, 38 bilinear Resize nodes), 1×3×320×320,
--metal -O, min of 3 interleaved rounds:DeviceSync*)Outputs match the CPU runtime to 6e-7 max abs (f32 accumulation order).
Two caveats I'd rather state than have you find:
DeviceSyncToHostis 91% of the Metal profile because 33OptMaxPoolnodes still have no Metal kernel and force 40 host round-trips per inference. Resize was necessary but not sufficient; MaxPool is the next one that matters.dump --profileare encode time, not GPU execution (the sync nodes absorb that), so I'm quoting only the end-to-end figure.GpuResizeis backend-agnostic and CUDA would need only a launch function, but there's no NVIDIA GPU on my machine, so I haven't written code I can't run. Happy for someone with the hardware to take it.Testing
test-metal22762 passed / 0 failed (630 of them Resize node tests, which exercise the kernel — I checked the nodes actually land onMetalResizerather than silently falling back).onnx-tests.sh 1_19_1green.cargo fmt --all --checkandcargo clippyclean.🍍