Skip to content

spec(GDN-MOE-BF16-OUT): the GDN recurrence output and the z gate are f32 on every MoE checkpoint, and both references keep them bf16 - #1173

Merged
localai-bot merged 2 commits into
mainfrom
row/SPEC-GDN-MOE-BF16-OUT
Aug 18, 2026
Merged

spec(GDN-MOE-BF16-OUT): the GDN recurrence output and the z gate are f32 on every MoE checkpoint, and both references keep them bf16#1173
localai-bot merged 2 commits into
mainfrom
row/SPEC-GDN-MOE-BF16-OUT

Conversation

@localai-bot

Copy link
Copy Markdown
Collaborator

The GDN recurrence output dcore and the z gate are held in f32 on every MoE
checkpoint, while both reference engines keep them at the bf16 model dtype.
GdnOutDType resolves bf16 = dense_model and every call site passes
cfg.num_experts == 0, so the dense arm is already bf16 and only the MoE arm
pays. The cost is the largest per-layer GDN activation carried at double width
twice: written by the recurrence, read by the gated RMSNorm.

vLLM keeps both at the model dtype, and so does SGLang. A token gate cannot see
this: the tokens match and the goldens pass while the path moves twice the
bytes, which is the dtype-polarity case the protocol calls out by name.

The row is spec-only. No product code changes here, and every gate is PENDING.

Two findings surfaced while verifying the premise, and both are filed rather
than folded in. Narrowing the dtype does not on its own make packed GDN decode
reachable on MoE: the eligibility also requires has_packed_ba, and
in_proj_ba is written at exactly one site, the dense loader, so the MoE and
GGUF loaders leave it split. That is a second, loader-side blocker and it is
tracked separately. The Triton AOT arms are pinned to 48 or 32 linear V-heads,
so the 2.4T checkpoint misses all four of them and runs the hand kernels; the
27B is unaffected because it carries 48. Both are recorded as owed debt with a
named owner rather than fixed in this flow.

Landing this also loosens an assumption on an unmerged branch: once the MoE arm
can be bf16, PERF-GDN-BF16-CHAIN's third eligibility term stops being bounded
by model shape and is bounded only by its default-OFF toggle. No behaviour moves
in either merge order, so it is a review obligation, logged under ## Owed.

Refs #1168, #1169, #1170, #521.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:Opus-5 [Claude Code]

mudler added 2 commits August 18, 2026 00:39
…f32 on every MoE checkpoint, and vLLM keeps both bf16 (#1168, #1169, #1170)

`GdnOutDType(bool dense_model)` resolves bf16 for a dense checkpoint and f32 for a
MoE one, and all three call sites pass `cfg.num_experts == 0`. So on the MoE arms
the recurrence output `dcore`, the `z` gate and the gated-RMSNorm weight that must
match them all stay f32, which doubles four passes over the two largest per-layer
GDN activations.

vLLM allocates `core_attn_out` at `hidden_states.dtype` and slices `z` out of the
bf16 in_proj output, with no dense-versus-MoE branch anywhere. So this is a
deviation from the PRIMARY oracle rather than an SGLang-only difference, and it is
the exact shape AGENTS.md describes when it says a token gate cannot detect a dtype
that is too wide: the 35B gate is 315/315 BECAUSE f32 is the more precise error.

The tree already derived the whole finding in the comment above the function and
deferred it to "its later independently gated campaign". That campaign was never
opened. This spec opens it, and it is spec-only: no product code, no measurement.

Two findings changed the shape of the row while writing it, so both are filed with
an owner rather than carried as assumptions. Removing the redundant `dense_model`
term from the packed-decode eligibility does NOT reach packed decode on a MoE
model, because only the dense loader builds the merged `in_proj_ba` owner (#1169).
And all four GDN Triton AOT arms are pinned to 48 or 32 linear V-heads, so the
2.4T's 128 misses every one of them and runs the hand kernels the vendoring exists
to replace (#1170). Neither is fixed here; both are listed under `## Owed`.

The gap was verified against the four unmerged local dtype branches before the spec
was written. None narrows this default. Two collide with it, and the spec records
both: `row/REFACTOR-DTYPE-CONSISTENCY` relocates the function verbatim, and
`row/PERF-GDN-BF16-CHAIN` uses the MoE f32 default as an eligibility bound that
this change removes.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5-1m [Claude Code]
Spec and issue-index rows for #1168: GDN core/z stay f32 on every MoE
checkpoint while both references keep them at the bf16 model dtype. Adds
#1169 (packed GDN decode has a second, loader-side blocker) and #1170
(the Triton AOT arms are pinned to 48 or 32 linear V-heads) as owed debt.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:Opus-5 [Claude Code]
@localai-bot
localai-bot merged commit 825a61e into main Aug 18, 2026
9 of 19 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.

2 participants