feat(engine): E1 DeepSeek-style MoE gate (sigmoid, group top-k, bias) (#108) - #123
Conversation
Add family-agnostic fwd_moe_route_deepseek matching mlx-lm group_expert_select: sigmoid scoring, e_score_correction_bias for selection only, n_group/topk_group restriction, routed_scaling_factor, and norm_topk_prob (top_k > 1 only). Softmax fwd_moe path unchanged. Closes #108.
Code review: feat(engine): E1 DeepSeek-style MoE gate (#123)Thorough review of the full PR: SummaryThe implementation is solid. It follows the plan (imp-108-e1-deepseek-style-moe-gate.md) precisely, respects all design decisions (D1-D9), and has comprehensive test coverage including frozen mlx-lm goldens. No critical issues found. Positive observations
Issues found1. (Medium) No guard against zero-sum division in norm path/* S2: norm only when top_k > 1 and flag set */
if (top_k > 1 && p->norm_topk_prob) {
if (!MLXB_CHECK(mlx_sum_axis(&weight_sum, top_w, -1, true, s)))
goto cleanup;
if (!MLXB_CHECK(mlx_divide(&scores_tmp, top_w, weight_sum, s)))
goto cleanup;
}If all selected pre-bias sigmoid weights are zero (theoretically possible with extremely negative logits combined with bf16 underflow), This is consistent with mlx-lm's Suggestion (optional follow-up, not blocking): add something like: mlx_array zero_check = mlx_array_new();
if (!MLXB_CHECK(mlx_less(&zero_check, weight_sum, epsilon_scalar, s)))
goto cleanup;
// ... broadcast zeros to scores_tmp where zero_check ...Or simply document in the header that callers with potentially all-zero sigmoid scores should pre-validate. 2. (Low)
|
Code review: PR 123 (E1 DeepSeek-style MoE gate)Reviewed as senior staff against issue #108, plan Scope verdict: In-scope for #108. Family-agnostic route primitive only. No Verification performed:
Overall: Approve with nits. No merge-blocking correctness bug found. This is a clean E1 port and the right plug-in surface for E2 composition ( What looks solid
FindingsLow - nits / follow-ups (non-blocking)L1. Dim-based validation is mostly GPU-suite-only; CI will not see regressions.
Those checks are pure metadata ( L2. Bias rank is under-validated. int bias_ndim = (int)mlx_array_ndim(e_score_correction_bias);
if (bias_ndim < 1) return -1;
if (mlx_array_dim(e_score_correction_bias, bias_ndim - 1) != E)
return -1;MoEGate stores L3. Golden Case B seed comment is slightly off for bias. Gates match L4. Fine as a smoke, but a single-row compare against L5. Test helper duplication vs Accepted by the plan for suite separation. If E2 adds more MoE GPU tests, extract Non-issues / explicitly not requesting changes
Issue #108 checkbox map (reviewer ack)
Merge recommendationApprove. Land as-is, or optionally fold L1 (CPU validation hoist) and L3 (seed comment) if you want a tiny follow-up commit before merge. Nothing here should block #108 close or parent #104 gate-line acceptance once #107 is already in. E2 callers: pass zeros when bias absent, compose |
…review) Address review comment 5020600218 L1-L4: - L1: CPU prologue validation matrix in test_fwd_moe_api - L2: require bias rank-1 [E]; reject broadcastable multi-rank bias - L3: correct Case B golden seed comment (0.5 * second randn) - L4: batch/seq test compares each row to host_group_expert_select L5 helper extract and sibling-comment items remain parked.
|
Thanks - agree with the Approve-with-nits read and the intentional non-findings table. Took (landed in fa59b13):
Parked (per review):
Not mixing in sibling comment 5020570697 (zero-sum norm guard / style nits) - parity-sensitive; separate note if ever pursued. Plan/TDD cycles: |
Summary
Implements #108 (parent #104 E1 MoE infrastructure): DeepSeek V3/V3.2/V4-style MoE gate as a family-agnostic routing primitive.
Plan:
doc/plans/imp-108-e1-deepseek-style-moe-gate.mdAPI
fwd_moe_route_deepseek_params_t+fwd_moe_route_deepseek(...)[..., E], requirede_score_correction_bias[E]inds[..., K],scores[..., K](same contract as softmax route)Algorithm (mlx-lm
group_expert_select)Scope decisions
fwd_moeconvenience wrapper unchanged (DeepSeek composes route + switch + combine)k_drop == 0skips group masking rather than argpartition with kth=-1Tests
test_route_deepseek_sigmoid_topk_n_group_1test_route_deepseek_group_*e_score_correction_bias(S1 split)test_route_deepseek_scores_ignore_bias_for_valuesrouted_scaling_factortest_route_deepseek_routed_scaling_factornorm_topk_prob(incl. top_k==1 no-op)test_route_deepseek_norm_topk_prob_*test_route_deepseek_matches_mlx_lm_golden_vectorstest_fwd_moe_deepseek_compose_*Goldens frozen from mlx-lm
group_expert_select(n_group=1 norm+scale; n_group=4 + non-zero bias).Test plan
make test(CPU) green includingtest_fwd_moe_api./tests/test_fwd_moe_deepseek_gpugreen (21 cases)./tests/test_fwd_moe_gpustill green (softmax path untouched)Closes #108.