Skip to content

[WebGPU] Keep LayerNormalization arithmetic in FP32 - #32896

Merged
Jiajia Qin (qjia7) merged 1 commit into
microsoft:mainfrom
gyagp:fix/webgpu-layernorm-fp16-mean
Sep 29, 2026
Merged

Jiajia Qin (qjia7) merged 1 commit into
microsoft:mainfrom
gyagp:fix/webgpu-layernorm-fp16-mean

Conversation

@gyagp

@gyagp Yang Gu (gyagp) commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Description

Keep full LayerNormalization arithmetic in FP32 until the normalized value is converted to the output type. This prevents FP16 mean conversion from amplifying small FP32 rounding errors before subtraction, and applies to both ordinary and split normalization shaders.

Preserve the existing same-type SimplifiedLayerNormalization arithmetic used by fused RMSNorm kernels. Mixed-type normalization already uses FP32. Input/output storage types and test tolerances are unchanged.

Motivation and Context

LayerNorm_WebGPU.Float16 fails on a Radeon 880M with the D3D12 backend (driver 32.0.22024.3004) for full normalization at shapes {2,3} and {2,6}, with and without bias.

For {2,3}, the FP32 mean is -1.7499998807907104. Narrowing it toward zero gives -1.7490234375 in FP16. Subtracting this from the middle input, -1.75, and normalizing produces -0.004779815673828125 instead of zero, exceeding the existing 0.002 tolerance. The CPU oracle normalizes before converting to the output type.

WGSL permits either adjacent representable value when narrowing to a floating-point type, so the shader cannot assume round-to-nearest will recover the exact mean. A standalone D3D12 probe reproduces the conversion behavior on both AMD and WARP; enabling IEEE strictness does not resolve it.

The existing LayerNorm_WebGPU.Float16 test provides regression coverage. Its related tests also cover mixed types, FP32, scalar/vec2/vec4, split normalization, bias and statistics outputs. No additional tolerance adjustment or duplicate test is needed.

Validation

  • Clean Windows x64 Release build of onnxruntime_provider_test with WebGPU enabled (Ninja/MSVC), on the Radeon 880M machine above.
  • --gtest_filter=LayerNorm_WebGPU.*: all 5 tests pass, with no skips. The 4 numerical tests exercise 72 subcases with CPU fallback disabled, including 24 SimplifiedLayerNormalization subcases.
  • --gtest_filter=LayerNormTest.*:CudaKernelTest.*LayerNorm*: all 54 broader tests pass, with no skips, using ORT_TEST_RANDOM_SEED_VALUE=2345. These tests include CPU and WebGPU coverage as supported by each case.
  • The original LayerNorm_WebGPU.Float16 failure was reproduced before the change. An independent D3D12 arithmetic probe also improves from 10 failing comparisons to zero across 36 outputs at the original tolerance.
  • Changed lines pass clang-format 20.1.8; git diff --check passes.

Narrowing the mean to FP16 before subtraction can amplify a small FP32
rounding error into a full FP16 step. On D3D12, round-to-zero conversion
causes LayerNorm_WebGPU.Float16 to exceed its existing tolerance for
small normalization dimensions.

Normalize full LayerNormalization in FP32 in both the ordinary and split
shader paths, converting to the output type after normalization. Preserve
same-type SimplifiedLayerNormalization arithmetic to maintain agreement
with the fused RMSNorm kernels.

The existing LayerNorm_WebGPU tests cover the affected behavior; input and
output storage types and test tolerances remain unchanged.
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@gyagp
Yang Gu (gyagp) marked this pull request as ready for review September 29, 2026 05:35
Copilot AI balanced review requested due to automatic review settings September 29, 2026 05:35
@gyagp

Copy link
Copy Markdown
Contributor Author

Jiajia Qin (@qjia7) PTAL

@gyagp

Copy link
Copy Markdown
Contributor Author

/run bots

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟒 Approval recommended

The focused change is correct and covered by existing WebGPU tests across relevant shader paths.

Review effort: Balanced
Findings: None

What changed in this PR

Keeps WebGPU LayerNormalization arithmetic in FP32 while preserving existing SimplifiedLayerNormalization behavior. No actionable issues found.

Changes:

  • Selects FP32 normalization for standard and mixed-type normalization.
  • Preserves same-type RMSNorm arithmetic.
File Description
onnxruntime/​core/​providers/​webgpu/​nn/​layer_norm.cc Updates normalization arithmetic type selection.

πŸ’‘ Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@qjia7

Copy link
Copy Markdown
Contributor

The request was received. Approve workflow runs. Thanks.

@qjia7
Jiajia Qin (qjia7) enabled auto-merge (squash) September 29, 2026 05:44
@qjia7
Jiajia Qin (qjia7) merged commit e927db3 into microsoft:main Sep 29, 2026
95 of 96 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants