Skip to content

layernorm: FP32 SimplifiedLayerNorm/SkipSLN to prevent MoE routing collapse - #5259

Open
rlegithub wants to merge 1 commit into
ROCm:developfrom
rlegithub:pr/gptoss-sln-fp32
Open

rlegithub wants to merge 1 commit into
ROCm:developfrom
rlegithub:pr/gptoss-sln-fp32

Conversation

@rlegithub

Copy link
Copy Markdown

Summary

Keeps FP32 variance through rsqrt and the gamma multiply for SimplifiedLayerNormalization / SkipSimplifiedLayerNormalization, so the router logits feeding the MoE stay FP32. fp16 rounding at this point collapses top-k expert routing on GPT-OSS-20B (wrong experts → garbage decode).

  • parse_simplified_layer_normalization.cpp, parse_skip_simplified_layer_normalization.cpp
  • find_skip_simplified_layer_norm isolates the SLN subgraph (fuse_attention.cpp) and compiles it as an MLIR group (fuse_mlir.cpp) preserving the FP32 gamma multiply
  • skip_simplified_layer_norm kernel

2 of 3 PRs enabling GPT-OSS-20B (with the fused MoE op and GQA-attention-sink PRs).

Test plan

  • CI
  • Verified on gfx1151: with FP32 SLN, GPT-OSS-20B routes correctly and decodes coherently; without it, routing collapses.

…llapse

Keeps FP32 variance through rsqrt and the gamma multiply for SimplifiedLayerNorm
and SkipSimplifiedLayerNorm so the router logits stay FP32 -- fp16 rounding here
collapses MoE top-k routing on GPT-OSS. Adds find_skip_simplified_layer_norm to
isolate the SLN subgraph (fuse_attention.cpp) and compiles it as an MLIR group
(fuse_mlir.cpp) + a skip_simplified_layer_norm kernel.

Co-Authored-By: Claude <noreply@anthropic.com>
float result = (x_val + sk_val) * inv_std * g_val;
output[token_idx * hidden_size + i] = __float2half(result);
}
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We already provide a layernorm kernel through the reduction kernels

// Each thread applies normalization in FP32 and writes fp16 output
for(index_int i = thread_idx; i < hidden_size; i += BLOCK_SIZE)
{
float x_val = __half2float(input[token_idx * hidden_size + i]);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This loads the input twice. The reduction kernel already handles this in an efficient manner,.

@rlegithub
rlegithub marked this pull request as ready for review September 14, 2026 21:21
@rlegithub
rlegithub requested a review from causten as a code owner September 14, 2026 21:21
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.

2 participants