Skip to content

perf(moe): preserve squared-ReLU fused MoE kernel behind a dedicated flag (#268) - #280

Merged
inureyes merged 1 commit into
mainfrom
perf/issue-268-preserve-relu2-kernel
Jun 14, 2026
Merged

inureyes merged 1 commit into
mainfrom
perf/issue-268-preserve-relu2-kernel

Conversation

@inureyes

Copy link
Copy Markdown
Member

Summary

Step 3b of #268 investigated wiring nemotron-h's MoE into the fused decode kernel. nemotron-h's experts are fc1 → relu² → fc2 (squared ReLU, not SwiGLU), so a dedicated fc1+relu² kernel was built (fc2 reuses the existing moe_down_kernel).

Finding: it's correct but performance-neutral on nemotron-h. Byte-identical output, but decode is unchanged/slightly lower (54.9 → 54.7 tok/s). nemotron-h's decode is dominated by its 23 Mamba2 + 6 attention layers, so the MoE expert GEMV is a small, already-efficient slice. nemotron-h's 0.60× gap is the hybrid SSM/attention path, not the MoE expert kernel.

What this PR does

Rather than discard a correct kernel, keep it in the tree behind its own flag MLXCEL_FUSED_MOE_RELU2, separate from the default MLXCEL_FUSED_MOE (which stays on gather_qmm for nemotron — no regression). This preserves the kernel as referenceable, compilable, testable code for a future squared-ReLU MoE model whose decode is MoE-dominated rather than Mamba-hybrid.

Validation

  • Default MLXCEL_FUSED_MOE: nemotron-h output byte-identical to fused-off (stays on gather_qmm, no behavior change).
  • MLXCEL_FUSED_MOE_RELU2: output byte-identical to the reference (kernel correct).
  • cargo fmt --check + cargo clippy clean.

Refs #268.

…flag (#268)

nemotron-h's MoE experts are fc1 -> relu² -> fc2 (squared ReLU, not SwiGLU).
A fused decode path for them was built and validated byte-identical, but it is
performance-NEUTRAL on nemotron-h-30b (54.9 -> 54.7 tok/s): nemotron's decode is
dominated by its 23 Mamba2 + 6 attention layers, so the MoE expert GEMV is a
small, already-efficient slice. The finding is that nemotron-h's 0.60x decode
gap is the hybrid SSM/attention path, not the MoE expert kernel.

Rather than discard the kernel, keep it in the tree behind its own flag
MLXCEL_FUSED_MOE_RELU2 (separate from the default MLXCEL_FUSED_MOE, which stays
on gather_qmm for nemotron — no regression). The fc1+relu² kernel produces
act_g[K, Dff]; fc2 reuses moe_down_kernel. Revive it for a future squared-ReLU
MoE model whose decode is MoE-dominated rather than Mamba-hybrid.

Verified: default flag leaves nemotron on gather_qmm (byte-identical to off);
MLXCEL_FUSED_MOE_RELU2 path byte-identical to the reference. fmt + clippy clean.
@inureyes inureyes added type:performance Performance improvements area:core mlxcel-core: MLX FFI, primitives, KV cache, layers platform:macos macOS (Apple Silicon) specific priority:low Low priority labels Jun 14, 2026
@inureyes
inureyes merged commit 6c825f8 into main Jun 14, 2026
5 checks passed
@inureyes
inureyes deleted the perf/issue-268-preserve-relu2-kernel branch June 14, 2026 09:38
inureyes added a commit that referenced this pull request Jun 14, 2026
…#283)

* docs(moe): document MLXCEL_FUSED_MOE flags, per-model gains, and M5 follow-up (#268)

Add a usage/flags section to the fused decode-MoE design doc: the
MLXCEL_FUSED_MOE / MLXCEL_FUSED_MOE_SGY / MLXCEL_FUSED_MOE_RELU2 env vars, the
measured per-model decode gains on M1 Ultra (gemma4 +13%, qwen3.5 +8.7%, dots
+4.7%, qwen3-30b +3.5%, nemotron ~0%), the f16-jitter-class parity caveat, and
the list of covered models. Mark roadmap steps 3-4 done (#278/#279/#280/#281)
and add step 5: validate on M5, then decide on flipping the flag default-on.

* docs(moe): reference the M5 validation issue (#282)
@inureyes inureyes added this to the 0.3 milestone Jun 21, 2026
@inureyes inureyes self-assigned this Aug 31, 2026
@inureyes inureyes added the status:done Completed label Sep 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core mlxcel-core: MLX FFI, primitives, KV cache, layers platform:macos macOS (Apple Silicon) specific priority:low Low priority status:done Completed type:performance Performance improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant