Do not fuse LayerNorm when ReduceMean has keepdims=0 - #31144
Conversation
LayerNormFusion and SimplifiedLayerNormFusion matched the ReduceMean nodes without looking at the keepdims attribute. With keepdims=0 the reduced dim is dropped, so the Sub and Div that follow broadcast along a different axis and the sub-graph does not compute a layer norm. The fusion replaced it anyway. Depending on the shapes that produced either a silently wrong result, or an invalid graph when the Div output was rank 1 and got picked as the scale input of the node that replaced the Div itself, which fails at session init with "Node input 'nm' is not a graph input, initializer, or output of a previous node". Check keepdims on all three ReduceMean match sites and skip the fusion when it is 0. Real layer norm exports leave keepdims at its default of 1, so nothing that fused before stops fusing.
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
This PR fixes an optimizer correctness bug in LayerNormFusion and SimplifiedLayerNormFusion where ReduceMean nodes with keepdims=0 could be incorrectly matched and fused into a layer-norm op, even though dropping the reduced dimension changes broadcasting semantics and can make the subgraph non-equivalent (or even produce an invalid graph).
Changes:
- Add a
keepdimsguard forReduceMeanat all LayerNorm fusion match sites so fusion is skipped whenkeepdims=0. - Add new graph transformer tests to ensure no fusion occurs for
keepdims=0patterns in both the full and simplified LayerNorm fusions.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| onnxruntime/core/optimizer/layer_norm_fusion.cc | Adds a helper to require ReduceMean keeps reduced dims, and applies it at each fusion match site to prevent incorrect fusions. |
| onnxruntime/test/optimizer/graph_transform_test_layernorm.cc | Adds regression tests verifying that keepdims=0 ReduceMean patterns do not fuse into LayerNormalization / SimplifiedLayerNormalization. |
|
@microsoft-github-policy-service agree |
|
Thanks for the review. The automated summary matches the change, and it did not raise anything, so no code change here. To restate the scope for a human reviewer: the guard is only on Happy to adjust anything. This is my first PR here, so let me know if the Azure Pipelines runs need authorizing. |
Fixes #30513
LayerNormFusionandSimplifiedLayerNormFusionmatch theReduceMeannodes without checkingkeepdims. Whenkeepdims=0the reduced dim is dropped, so the followingSubandDivbroadcast along a different axis and the sub-graph is not a layer norm, but the fusion replaces it anyway.Two ways that goes wrong today:
Divoutput is rank 1, so the scale-selection loop picks it as thescaleinput of the node that replaces theDivitself. Session creation then fails withNode input 'nm' is not a graph input, initializer, or output of a previous node.The fix checks
keepdimsat the threeReduceMeanmatch sites and skips the fusion when it is 0. Layer norm exports leavekeepdimsat its default of 1, so nothing that fused before stops fusing.Verified on Linux x64, CPU EP, built from this branch with gcc 13:
InvalidArgument.keepdims=0now produce output matching the same model run with graph optimizations disabled. Before the change they did not match.LayerNormFusion_ReduceMeanNoKeepDims_NoFusionandSimplifiedLayerNormFusion_ReduceMeanNoKeepDims_NoFusionfail before the change and pass after.onnxruntime_test_all --gtest_filter='GraphTransformationTests.*': 362 passed, 15 skipped (WebGPU), 0 failed. The fullonnxruntime_test_all: 1884 passed, 17 skipped, 0 failed. clang-format 20.1.8 clean on both changed files.Not verified: non-CPU execution providers, Windows and macOS builds, and training-enabled builds (
ENABLE_TRAINING_CORE).Thanks to @XYZboom for the report and the reproducer.