[WebGPU] Add GRU operator support - #29840
Conversation
Implements the GRU operator for the WebGPU execution provider, following the
existing WebGPU LSTM kernel.
Each timestep is computed in two passes because, for linear_before_reset = 0,
the recurrent term (r (.) H_prev) * Rh^T mixes reset-gate values across hidden
units and therefore cannot be produced by a single per-unit thread:
- GruGateProgram computes the update (z) and reset (r) gates for the whole
[batch, hidden] tensor.
- GruHiddenProgram computes the hidden gate and the new state
Ht = (1 - z) (.) h + z (.) H_prev.
Supports bias, forward/reverse/bidirectional directions, sequence_lens masking,
the layout attribute, clip, and both linear_before_reset modes. Registered for
opsets 7-13 and 14+ with float (T) and int32 (T1) type constraints.
Coverage comes from the existing GRU operator tests, which now also run against
the WebGPU EP; cases using activations the kernel does not implement
(e.g. LeakyRelu/ScaledTanh) are excluded from the WebGPU run.
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
@microsoft-github-policy-service agree |
Review: PR #29840 — [WebGPU] Add GRU operator support (head
|
There was a problem hiding this comment.
Pull request overview
Adds GRU operator support to the WebGPU Execution Provider by introducing a two-pass GRU timestep implementation (gate pass + hidden/state pass), wiring it into the WebGPU kernel registry, and updating existing GRU OpTester coverage to conditionally exclude WebGPU when unsupported activations are requested.
Changes:
- Implement WebGPU GRU kernel (
GruGateProgram,GruHiddenProgram, and state copy helper) with support for direction,sequence_lens,layout,clip, bias, and bothlinear_before_resetmodes. - Register GRU kernels for ONNX opsets 7–13 and 14+ in the WebGPU EP.
- Update existing GRU CPU test helper to skip WebGPU execution for activation functions not implemented by the WebGPU kernel.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| onnxruntime/test/providers/cpu/rnn/deep_cpu_gru_op_test.cc | Exclude WebGPU EP for GRU test cases using unsupported activations; refactors excluded-provider handling. |
| onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc | Registers WebGPU GRU kernel create-info entries for opsets 7–13 and 14+. |
| onnxruntime/core/providers/webgpu/rnn/gru.h | Declares WebGPU GRU programs and kernel class. |
| onnxruntime/core/providers/webgpu/rnn/gru.cc | Implements GRU shader programs, kernel ComputeInternal, and kernel registrations. |
|
Thanks for the review. I addressed the suggested cleanup by validating the B, sequence_lens, and initial_h shapes, validating supported activations during kernel construction, and adding bounds checking for hidden_size. The changes are pushed in a3be53e. |
|
For a follow-up, I’d be happy to add dedicated WebGPU-only GRU tests with CPU fallback disabled, or work on FP16 support. Please let me know which direction would be most useful. |
Please feel free to choose based on your interest :) - that was suggested by my AI reviewer. We don't have concrete requirements for either at this point. |
Head branch was pushed to by a user without write access
|
Hi @hariharans29, thank you for approving the PR earlier. Some checks subsequently failed, so I pushed 183a6db to fix the GRU test failure caused by adding the layout attribute to opset-7 tests. Existing tests now omit the attribute, while the new layout=1 test runs with opset 14. The latest workflows are currently waiting for maintainer approval, so I’m unable to validate the fix through CI. Could you please approve the pending workflows or rerun the checks? The earlier failures were caused by the test setup rather than the WebGPU GRU implementation. |
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
|
@hariharans29 I investigated the failed checks. The initial failures were caused by the test setup: existing opset-7 GRU tests were receiving an unsupported layout attribute. After fixing that, the only remaining PR-specific failure was that the new layout test initialized R with 9 values instead of the required 27. |
It seems like it may still be failing some tests ? |
|
@hariharans29 Thank you for the follow-up. Yes, please don’t trigger another Azure Pipelines run just yet. I’ve been analyzing the failed runs since yesterday and making a few local changes to reduce the failures. I’ll let you know once I have something I’m confident is ready to test. |
Sure, thank you for the analysis |
Head branch was pushed to by a user without write access
|
Hi @hariharans29,I investigated the failed CI runs and identified that the failures came from the test setup rather than the WebGPU GRU implementation. The changes and fixes are:
The completed CI runs initially showed many failures, but every actual failure was the same I independently recalculated the expected outputs for the corrected input. The maximum difference was approximately The consolidated fixes are in commits |
Description
Adds the
GRUoperator to the WebGPU execution provider, following the existing WebGPULSTMkernel. Registered for opsets 7-13 and 14+, with float (T) and int32 (T1) type constraints.Each timestep is computed in two passes because, for
linear_before_reset = 0, the recurrent term(r (.) H_prev) * Rh^Tmixes reset-gate values across hidden units and so cannot be produced by a single per-unit thread:GruGateProgramcomputes the update (z) and reset (r) gates for the whole[batch, hidden]tensor. Forlinear_before_reset = 0it emitsr (.) H_prevdirectly; forlinear_before_reset = 1it emitsrso the reset is applied after the recurrent matmul.GruHiddenProgramcomputes the hidden gate and the new stateHt = (1 - z) (.) h + z (.) H_prev.Supported: bias, forward / reverse / bidirectional directions,
sequence_lensmasking, thelayoutattribute,clip, and bothlinear_before_resetmodes. Activations are limited to Sigmoid/Tanh/Relu (as in the WebGPU LSTM kernel).Motivation and Context
Resolves #29452. GRU was the natural follow-up to the recently added WebGPU LSTM support, letting models with GRU nodes run on the WebGPU EP.
Testing
Coverage comes from the existing GRU operator tests in
deep_cpu_gru_op_test.cc, which now also execute against the WebGPU EP (base_testeriterates the WebGPU EP when built with--use_webgpu). Cases using activations the kernel does not implement (e.g.LeakyRelu/ScaledTanh) are excluded from the WebGPU run via the shared test helper.The gate math and buffer indexing were cross-checked against an independent ONNX-spec GRU reference for both
linear_before_resetmodes, with and without bias (match to ~1e-16). Validation on real WebGPU hardware is left to CI.