Skip to content

models: fix GDN normalization - #156

Closed
danielhanchen wants to merge 1 commit into
base/upstream-9723942adfrom
gdn/fla-l2norm
Closed

models: fix GDN normalization#156
danielhanchen wants to merge 1 commit into
base/upstream-9723942adfrom
gdn/fla-l2norm

Conversation

@danielhanchen

@danielhanchen danielhanchen commented Aug 31, 2026

Copy link
Copy Markdown
Member

Fixes GDN q/k normalization to use x * rsqrt(sum(x^2) + eps) instead of x / max(sqrt(sum(x^2)), eps), matching the official Qwen FlashQLA repo, FLA, Transformers, vLLM, and SGLang.

Affects qwen35, qwen35moe, qwen3next, qwen4exp, kimi-linear, kimi-k3, and bailingmoe3. ggml_l2_norm and RWKV7 are unchanged.

@danielhanchen
danielhanchen requested a review from CISC as a code owner August 31, 2026 03:22
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-31T04:46:28.722622Z c03dc68 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f011d805c7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/models/models.h Outdated
Comment on lines +13 to +17
// flash-linear-attention's l2norm, x * rsqrt(sum(x*x) + eps), with eps INSIDE the root.
// ggml_l2_norm is x / max(sqrt(sum(x*x)), eps), i.e. torch.nn.functional.normalize: right for
// rwkv7-base, which passes normalize's own 1e-12, wrong here. transformers hit the same thing
// and fixed it in huggingface/transformers#40842.
// rms_norm already carries eps inside the root, so this needs no new ggml op.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Condense the helper comment

Condense this five-line, mid-sentence-wrapped comment to the essential one or two lines. The repository explicitly requires concise code comments and forbids hard-wrapping them, so this block adds avoidable maintenance noise to a globally included header.

AGENTS.md reference: AGENTS.md:L74-L77

Useful? React with 👍 / 👎.

@danielhanchen danielhanchen changed the title models: use flash-linear-attention's l2norm for gated delta net q/k models: fix Qwen3-Next, GDN normalization Aug 31, 2026
@danielhanchen danielhanchen changed the title models: fix Qwen3-Next, GDN normalization models: fix GDN normalization Aug 31, 2026
The GDN q/k normalization is defined by flash-linear-attention as

    l2norm(x) = x * rsqrt(sum(x*x) + eps)

with eps inside the root. Every GDN call site in the tree uses ggml_l2_norm
instead, which is x / max(sqrt(sum(x*x)), eps), i.e.
torch.nn.functional.normalize - its CUDA kernel cites that page.

The clamp never engages at these magnitudes, so in practice llama.cpp
normalizes with no epsilon at all where the reference has one inside the
root.

transformers made the same substitution when it first added Qwen3-Next and
corrected it three days later in huggingface/transformers#40842, 'Fix the
misalignment between the l2norm in GDN of Qwen3-Next and the implementation
in the FLA library'. vLLM and SGLang vendor FLA rather than reimplementing
it, so neither ever had the clamp.

eps keeps coming from the checkpoint, exactly as every call site already
passed it. The references hardcode 1e-6 for this norm; that is a separate
question and the two agree on every GDN checkpoint in the wild.

ggml_l2_norm itself is correct and unchanged, as is rwkv7-base, its original
caller, which passes normalize's own default eps of 1e-12.

No new ggml op: rms_norm already carries eps inside the root, so
rms_norm(x, eps/n) * (1/sqrt(n)) is exactly x * rsqrt(sum(x*x) + eps).
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.

1 participant