Repository navigation
[ET-VK][conv2d] Skip the store rounding of texels computed in f16 - #24940
Merged
Merged
Conversation
## Ulterior Motive Optimizing the FP16 1x1 convolutions of the DSR model on mobile GPUs. ## Rationale **What**: `f16vec4` texels are stored to rgba16f images without the shader generator's FP32 rounding, and the conv2d epilogue (residual, scale, clamp, ReLU, leaky ReLU) computes in the shader's texel type. Half pointwise (`conv2d_pw_tiled`), direct (`conv2d_tiled`) and buffer-input im2col (`conv2d_gemm`) convolutions now pass their f16 accumulators to the store as they are. **Why**: A texel computed in f16 is exact in f16, so the rounding never changes it, but it costs about 40 instructions per stored texel on Adreno 740. The epilogue took and returned `vec4`, so every Half store paid for the rounding, with or without an epilogue. With this commit three DSR 1x1 layers take 0.84 to 0.93 of the time on a Pixel 9 Pro XL (Mali-G715) and 0.87 to 0.91 on a Galaxy S23 (Adreno 740), and a DSR 3x3 direct convolution 0.92 and 0.96. A Galaxy S26 Ultra (Adreno 840) is within noise. ## Details - Store rounding - **Before**: Every store to an rgba16f image passes its texel through `round_to_f16(vec4)`, which rounds to the nearest f16 with FP32 bit manipulation because some devices round toward zero. An `f16vec4` texel converts to `vec4` and is rounded too, which never changes it. - **After**: The generator also declares `round_to_f16(f16vec4)`, which only widens. `f16vec4` is a type only where `GL_EXT_shader_explicit_arithmetic_types_float16` is enabled, so the overload is declared under `#ifdef HAS_FLOAT16_ACCUMULATION`, which the conv2d shaders that accumulate in f16 define before their output image declaration. Other shaders keep rounding their texels. - Epilogue - **Before**: `apply_epilogue()` computes in `vec4`; callers cast f16 accumulators to `vec4`. - **After**: It computes in `VEC4_T`, including the residual alpha multiply and the leaky ReLU slope, and the pointwise, direct and im2col shaders pass their accumulators without a cast. Where `VEC4_T` is `vec4` (Float variants, depthwise and transposed convolutions, texture-input im2col), the code compiles to the same Adreno 740 ISA. - Epilogue parameters - **Before**: The alpha, slope and clamp bounds reach the shaders as given. - **After**: For the shaders that compute the epilogue in f16, the host rounds them to the nearest f16, ties to even, so their conversion to `f16vec4` is exact even where the GPU rounds conversions toward zero. `half_to_float` and `float_to_half` move out of `StagingBuffer.cpp`'s anonymous namespace for this. Outputs without an epilogue are bit-identical. With an epilogue, Half variants that compute in f16 round to f16 after the residual add, the scale and the leaky ReLU, where they rounded once at the store before. Clamps are bit-identical: rounding is monotonic, so clamping an f16 value to the rounded bounds gives the rounded clamp of it. `FLT_MAX` bounds round to infinity. 16 SPIR-V modules change: - `conv2d_pw_tiled_half`, `conv2d_pw_tiled_bufw_half`, `conv2d_pw_tiled_4x8_half`, `conv2d_pw_tiled_4x8_bufw_half` - the 11 Half `conv2d_tiled` modules (`conv2d_1x1x4_half`, `conv2d_2x2x8_border_half`, ...) - `conv2d_gemm_buffer_half` 32 more modules (the Float conv2d modules, and the Half depthwise, transposed and texture-input im2col modules) differ in the form of the epilogue's conversions and compile to identical Adreno 740 ISA. Differential Revision: [D130986955](https://our.internmc.facebook.com/intern/diff/D130986955/) ghstack-source-id: 469962071 Pull-Request: #24857
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/24940
Note: Links to docs will display an error until the docs builds have been completed. ❗ 1 Active SEVsThere are 1 currently active SEVs. If your PR is affected, please view them below: ⏳ 17 Pending, 1 Unrelated FailureAs of commit 888e31c with merge base 115655c ( BROKEN TRUNK - The following job 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. |
SS-JIA
approved these changes
Nov 12, 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.
This PR was created by the merge bot to help merge the original PR into the main branch.
ghstack PR number: #24857 by @SS-JIA
^ Please use this as the source of truth for the PR details, comments, and reviews
ghstack PR base: https://github.com/pytorch/executorch/tree/gh/SS-JIA/708/base
ghstack PR head: https://github.com/pytorch/executorch/tree/gh/SS-JIA/708/head
Merge bot PR base: https://github.com/pytorch/executorch/tree/gh/SS-JIA/707/orig
Merge bot PR head: https://github.com/pytorch/executorch/tree/gh/SS-JIA/708/orig
Differential Revision: D130986955
@diff-train-skip-merge