Skip to content

Commit e354e30

Browse files
yindingclaude
andcommitted
Fix FP4 swapAB L1 accuracy: align routing-weight fold order with non-swap
The L1 swap epilogue folded the per-token routing weight into the value before the per-token amax / FP8 quantization, whereas the non-swap path folds it into sf_inv afterwards. The differing FP32 multiply order (value*weight)*sf_inv vs value*(weight*sf_inv) produced occasional FP8 scale-factor mismatches, costing ~6 GSM8K points (0.890 vs 0.952) and surfacing as multi-rank run-to-run nondeterminism. Fold the weight after amax (weighted sf_inv) in the swap path to match non-swap; the L1 output becomes bit-identical to non-swap and GSM8K recovers to ~0.95 at full swap performance. Keep the N32 L1 swapAB bucket avoidance: with the weight-fold bug fixed, run_swap_ab_l1<32> is revealed to have a separate accuracy bug (N=32 -> 0.893 vs N=64 -> 0.953), so 25-32 token cases route to the <64> bucket. Add a DG_SM90_FP4_SWAP_AB env kill-switch (default on) to force the non-swap path for A/B accuracy comparison. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent b25bd49 commit e354e30

2 files changed

Lines changed: 12 additions & 3 deletions

File tree

csrc/apis/sm90_mega.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,15 @@ static FP4SM90APIDefaults get_fp4_sm90_api_defaults(
155155
expected_tokens_per_expert >= 0.375f and expected_tokens_per_expert < 0.75f) or
156156
(fp4_pro_shape and
157157
expected_tokens_per_expert >= 0.25f and expected_tokens_per_expert < 0.375f));
158+
// swapAB on/off kill-switch (default ON). Set DG_SM90_FP4_SWAP_AB=0 to force
159+
// the non-swap path for A/B accuracy comparison.
160+
const bool swap_ab_env_enabled = get_env<int>("DG_SM90_FP4_SWAP_AB", 1) != 0;
158161
const bool default_swap_ab =
162+
swap_ab_env_enabled and
159163
(fp4_flash_shape or fp4_pro_shape) and
160164
expected_tokens_per_expert > 0.0f and expected_tokens_per_expert <= 24.0f;
161165
const bool default_swap_ab_fast_amax =
166+
swap_ab_env_enabled and
162167
fp4_pro_shape and
163168
expected_tokens_per_expert >= 12.0f and expected_tokens_per_expert <= 24.0f;
164169
return {

deep_gemm/include/deep_gemm/impls/sm90_fp8_fp4_mega_moe.cuh

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1945,10 +1945,11 @@ sm90_fp8_fp4_mega_moe_impl(void* y,
19451945
const float weight_0 = *l1_topk_weights_buffer
19461946
.get_data_buffer(m_idx + token_0)
19471947
.get_base_ptr<float>();
1948-
v0 = silu(g0) * u0 * weight_0;
19491948
if constexpr (kSwapABFastAmaxActive) {
1949+
v0 = silu(g0) * u0 * weight_0;
19501950
swap_v0[i] = v0;
19511951
} else {
1952+
v0 = silu(g0) * u0;
19521953
smem_cd_swap_l1_fp32[token_0 * L1_OUT_BLOCK_N + out_col_base] = v0;
19531954
}
19541955
}
@@ -1962,10 +1963,11 @@ sm90_fp8_fp4_mega_moe_impl(void* y,
19621963
const float weight_1 = *l1_topk_weights_buffer
19631964
.get_data_buffer(m_idx + token_1)
19641965
.get_base_ptr<float>();
1965-
v1 = silu(g1) * u1 * weight_1;
19661966
if constexpr (kSwapABFastAmaxActive) {
1967+
v1 = silu(g1) * u1 * weight_1;
19671968
swap_v1[i] = v1;
19681969
} else {
1970+
v1 = silu(g1) * u1;
19691971
smem_cd_swap_l1_fp32[token_1 * L1_OUT_BLOCK_N + out_col_base] = v1;
19701972
}
19711973
}
@@ -2047,11 +2049,13 @@ sm90_fp8_fp4_mega_moe_impl(void* y,
20472049
const float v = smem_cd_swap_l1_fp32[token * L1_OUT_BLOCK_N + col];
20482050
amax = cute::max(amax, cute::abs(v));
20492051
}
2052+
const float wtok = *l1_topk_weights_buffer.get_data_buffer(m_idx + token).get_base_ptr<float>();
2053+
amax *= cute::abs(wtok);
20502054
float2 amax_pair = {amax, amax};
20512055
float2 sf_pair, sf_inv_pair;
20522056
sm90_fp8_fp4_mega_moe_get_e4m3_sf_and_sf_inv(amax_pair, sf_pair, sf_inv_pair);
20532057
const float sf = sf_pair.x;
2054-
const float sf_inv = sf_inv_pair.x;
2058+
const float sf_inv = wtok * sf_inv_pair.x;
20552059

20562060
auto sf_base_ptr = l2_sf_buffer.get_base_ptr<float>();
20572061
const uint32_t token_idx = pool_block_idx * BLOCK_M + token;

0 commit comments

Comments
 (0)