[WebGPU] Add transpose-optimizer handlers for Elu and the contrib GELU variants - #32118
Open
Ananya Anand (4n4ny4) wants to merge 3 commits into
Open
[WebGPU] Add transpose-optimizer handlers for Elu and the contrib GELU variants#32118Ananya Anand (4n4ny4) wants to merge 3 commits into
Ananya Anand (4n4ny4) wants to merge 3 commits into
Conversation
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 27 out of 34 changed files in this pull request and generated no new comments.
Suppressed comments (4)
onnxruntime/core/optimizer/conv_activation_fusion.cc:210
- QuickGelu's schema default is
alpha = 1.702f(core/graph/contrib_ops/contrib_defs.cc:624), but an omitted attribute is encoded here as 1.0. A validcom.microsoft.QuickGelunode without an explicit alpha will therefore be fused as SiLU and produce different results.
activation_params.push_back(alpha_attr == nullptr ? 1.0f : alpha_attr->f());
onnxruntime/core/optimizer/conv_activation_fusion.cc:108
- An explicitly empty optional bias input is semantically absent, but it still leaves two entries in
InputDefs(). This check rejectsFastGelu(X, "")even though the new transpose handler correctly treats that form as elementwise, so layout propagation succeeds but the intended Conv fusion still does not happen. CheckExists()for the optional slot, as other optimizer code does.
This issue also appears on line 210 of the same file.
return activation_node.InputDefs().size() == 1;
onnxruntime/test/providers/webgpu/activation_snippet_test.cc:6
std::setprecisionis declared by<iomanip>, which this new test does not include. Depending on transitive includes from gtest makes this translation unit non-portable and can fail to compile when those headers change.
#include <limits>
onnxruntime/core/providers/webgpu/nn/fuse_utils.cc:22
std::ostringstreamhonors the process locale, so after an application installs a locale with a comma decimal separator this can emit WGSL such as0,707..., causing shader compilation to fail. Shader literals must be locale-independent; imbue the classic locale before formatting.
std::string FloatLiteral(float value) {
std::ostringstream oss;
oss << std::setprecision(std::numeric_limits<float>::max_digits10) << value;
return oss.str();
Ananya Anand (4n4ny4)
force-pushed
the
webgpu-contrib-gelu-nhwc-reachability
branch
from
August 20, 2026 21:23
8c5c5ec to
78c472e
Compare
Ananya Anand (4n4ny4)
force-pushed
the
webgpu-contrib-gelu-nhwc-reachability
branch
2 times, most recently
from
August 23, 2026 06:25
365dbc6 to
b4ee98c
Compare
Jiajia Qin (qjia7)
previously approved these changes
Aug 26, 2026
Hariharan Seshadri (hariharans29)
previously approved these changes
Aug 28, 2026
Member
|
Can you please rebase with main ? For some reason, the 2 CI checks are not queueing. Hopefully a rebase fixes that. |
Hariharan Seshadri (hariharans29)
pushed a commit
that referenced
this pull request
Aug 30, 2026
### Description Extends the WebGPU Conv+activation fusion allowlist by eight kinds: QuickGelu, HardSwish, Elu, Gelu, Gelu(tanh), Softplus, ThresholdedRelu and Erf, each with a WGSL snippet for the generated-shader path and a matching branch in the im2col template. QuickGelu at alpha == 1 is a distinct shader because the multiply drops out entirely, so it carries its own `QuickGeluUnitAlpha` cache-key term to stop the two variants colliding in the pipeline cache. This also fixes the QuickGelu alpha fallback, which was `1.0f` rather than the schema default `1.702f`: attributes are materialized onto nodes during `Graph::Resolve()`, so the fallback was unreachable and could not change model output, but it was still wrong on paper and inconsistent with the standalone WebGPU QuickGelu kernel. Four of the eight (`Elu` and the three contrib GELU variants) also need a transpose-optimizer handler to fuse end to end, and since that map is shared cross-EP infrastructure rather than WebGPU code it lives in #32118; until that lands those four still execute correctly, just unfused. Covered by 35 new tests, including negative controls for Selu and the CPU EP, execution parity against unfused results, and one that strips QuickGelu's alpha after `Resolve()` so it actually fails without the fix. ### Motivation and Context These activations are common after convolutions. QuickGelu is how SiLU/Swish reaches the graph and HardSwish appears throughout MobileNet-class models, but each one previously forced a separate dispatch and a round trip through global memory. --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Co-authored-by: Ananya Anand <t-anaanand@microsoft.com> Co-authored-by: Ananya Anand <4n4ny4@users.noreply.github.com>
Models that already contain com.microsoft.Gelu, FastGelu or QuickGelu after a Conv never fused: layout propagation stopped at the activation, leaving a transpose wedged between the internal-NHWC Conv and the GELU, so ConvActivationFusion never saw them adjacent. Add layout handlers for the three contrib ops, plus ONNX Elu, which has the same gap. The Elu handler previously arrived here by inheritance from the WebGPU Conv activation PR this branch stacks on. That PR no longer carries it, because the transpose optimizer is shared cross-EP infrastructure rather than WebGPU code, so this commit owns the line outright. Inheritance was fragile: rebasing this branch after that PR dropped the line would have silently removed the handler with no conflict and no error. FastGeluFusion was also registered for cpu+cuda+dml only, so the tanh-GELU decomposition emitted by pre-opset-20 exporters never became com.microsoft.FastGelu on WebGPU. Register it for WebGPU too. WebGPU implements all three contrib kernels, so nothing is stranded on CPU. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> (cherry picked from commit ac4e398)
The handlers added here had no coverage at the transpose-optimizer layer. These build Transpose -> activation -> Transpose and assert the transposes cancel, which only happens if the optimizer actually pushed one through the activation. TransformerTester also runs each model and compares against the un-optimized baseline, so a handler that moved the Transpose but changed the maths fails too. Includes the case the FastGelu handler exists for: with a bias present the Transpose must NOT move, because bias_gelu_helper::CheckInputs requires a rank-1 bias whose length equals the last dimension of input 0, and a layout permutation moves a different axis into that position. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> (cherry picked from commit efcb879)
WebGpuConvEluFusionMatchesUnfusedResults needs the Elu transpose handler that this PR adds (onnx_transpose_optimization.cc), so it belongs here rather than in the PR below, where it can only fail. This re-adds it after the parent PR dropped it, matching the rule already used on this stack: a test that needs two layers lives at the top layer. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> (cherry picked from commit b4ee98c)
Ananya Anand (4n4ny4)
dismissed stale reviews from Hariharan Seshadri (hariharans29) and Jiajia Qin (qjia7)
via
August 31, 2026 00:28
0b20c16
Ananya Anand (4n4ny4)
force-pushed
the
webgpu-contrib-gelu-nhwc-reachability
branch
from
August 31, 2026 00:28
b4ee98c to
0b20c16
Compare
Contributor
Author
|
Rebased onto main. #32117 merged in the meantime, so the eight commits this was stacked on are gone. The push dismissed your approval, could you re-approve? Thank you! |
Jiajia Qin (qjia7)
approved these changes
Aug 31, 2026
Ananya Anand (4n4ny4)
enabled auto-merge (squash)
August 31, 2026 04:26
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.
Description
OrtExtendedHandlers()had no entries forcom.microsoft.Gelu,FastGeluandQuickGelu, and the ONNX map was missingElu, so layout propagation stopped at the activation and left a transpose wedged between the NHWC Conv and the activation whereConvActivationFusionnever saw them adjacent. Results stayed correct, the fusion just silently did not fire.FastGeluneeds a bespoke handler rather than a table entry because its optional bias is pinned to the last dimension, andbroadcast_node_handlerwould rank-normalize it into a rank-4 bias that failsbias_gelu_helper::CheckInputsoutright, so the handler pushes the transpose only when there is no bias.Elulives here rather than in #32117 because the transpose optimizer is shared cross-EP infrastructure, not WebGPU code. This also registersFastGeluFusionfor WebGPU, which was cpu, cuda and dml only, sinceGeluFusionandBiasGeluFusionalready landed in #32053. Covered by 6 fusion tests and 5 transpose-optimizer tests, including a negative test thatFastGeluwith a bias is left alone.Motivation and Context
Models often already contain contrib GELU nodes, since
QuickGeluFusionandGeluFusionrun before layout transformation, so without these handlers the Conv activation fusion never fires on exactly the models most likely to benefit. #32117 adds the WebGPU side of the same work and needs these handlers to fuse end to end.