metrale_model_layers/layers/moe/forward/
zero_expert.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! 2026-09-26: `MoeLayer::fp32_routing_active` and `MoeLayer::apply_zero_expert`, moved whole from
4//! `forward.rs`.
5//!
6//! Owner: model-layers (MoE).
7//! Invariants: none beyond the types.
8
9use super::*;
10
11impl MoeLayer {
12    /// 2026-09-25: Whether the FP32 routing path is on for this layer: the pre-MoE
13    /// norm then also writes an FP32 copy of the router input
14    /// (`residual_add_rms_norm_gatef32` into `moe_router_in_f32`), which
15    /// `batched_gate_logits` reads through `dense_gemm_f32in`. Needs a dense gate
16    /// (no `gate_nvfp4`), no correction bias, the `dense_gemm_f32in` and
17    /// `moe_topk_f32` kernels, and, checked last, the `fp32_routing` lever (on
18    /// only when `METRALE_FP32_ROUTING=1`).
19    pub fn fp32_routing_active(&self, levers: &crate::layers::ops::ModelLevers) -> bool {
20        self.gate_nvfp4.is_none()
21            && self.correction_bias_dev.is_none()
22            && self.dense_gemm_f32in.0 != 0
23            && self.moe_topk_f32.0 != 0
24            && levers.fp32_routing
25    }
26
27    /// 2026-09-25: Add the zero-expert term `out[t,:] += zero_accum[t] * x[t,:]`,
28    /// where `zero_accum` holds the weights of the selected zero experts that
29    /// the softmax+bias router folded out. It adds into `out` in place, so it
30    /// runs after the routed blend has written `out`, for the tokens whose
31    /// routing wrote `zero_accum`. No launch when `router_logits_n` equals
32    /// `num_experts`; an error when the kernel is missing.
33    pub fn apply_zero_expert(
34        &self,
35        out: metrale_gpu_runtime::gpu::DevicePtr,
36        x: metrale_gpu_runtime::gpu::DevicePtr,
37        n: u32,
38        ctx: &ForwardContext,
39        stream: u64,
40    ) -> Result<()> {
41        if self.router_logits_n as usize == ctx.config.num_experts {
42            return Ok(());
43        }
44        anyhow::ensure!(
45            self.moe_zero_expert_add_k.0 != 0,
46            "zero-expert model but moe_zero_expert_add kernel is absent from this build"
47        );
48        ops::moe_zero_expert_add(
49            ctx.gpu,
50            self.moe_zero_expert_add_k,
51            out,
52            x,
53            self.zero_accum_dev,
54            n,
55            ctx.config.hidden_size as u32,
56            stream,
57        )
58    }
59}