[CUDA] Skip FP4 QMoE fc1 activation expansion - #31479
Conversation
c62b6ae to
f713813
Compare
f713813 to
77dc84d
Compare
77dc84d to
b964e92
Compare
b964e92 to
f46110e
Compare
Multi-model review (5 reviewers: readability, correctness, adversarial, deep/spec, integration)Verdict: the index math is correct — I tried hard to break it and could not. Three reviewers independently confirmed the Confirmed correct (so nobody re-litigates it)
Major1. The The already-merged INT-path equivalent guards the identical rewrite, and even documents the mapping: // moe_gemv.cu:20-36
template <int CtaM>
__device__ __forceinline__ int act_source_row(const int* permuted_row_to_source_row, int num_rows,
int row, int offset_m) {
if (permuted_row_to_source_row == nullptr) return offset_m;
static_assert(CtaM == 1, "source-row indirection assumes one expanded row per block");
return permuted_row_to_source_row[row] % num_rows;
}The FP4 version inlines the expression with neither the guard nor the comment. It is correct today only because Fix: hoist 2. The env knob is parsed on every
Fix: latch it in the constructor as 3. Every other 4. The new parity test cannot distinguish the indirection it exists to protect. With
The shape validates the modulus but not the indirection — which is the entire reason 5. The test has no positive control — it passes green if the fused GEMV never dispatched. The dispatch gate at 6. The header doc now describes the wrong buffer. The doc block still inherits Minor
Questions
Nice result on the perf side, and the fact that the INT path already landed the same transformation makes this a low-risk port. The two things I'd genuinely want before merge are #1 (the guard — it's three lines and prevents a silent-wrong-answer regression) and #4/#5 (make the test actually able to fail). 🤖 Reviewed with a 5-model review team (Claude Opus 5 · GPT-5.3-Codex · GPT-5.6 · Gemini 3.1 Pro), findings verified against the source. |
e7b7df9 to
efa4415
Compare
Description
Stacked on #31159; review only the top commit.
This removes the standalone FP4 QMoE fc1 activation expansion during GEMV decode. Instead, fc1 maps each permuted row back to its source token with
permuted_row_to_source_row[row] % num_rows; fc2 remains unchanged because it consumes the expanded fc1 output.Summary of Changes
ORT_DISABLE_FP4_GEMV_SKIP_EXPAND=1for same-binary comparison.num_tokens=3,top_k=8) with skip-expand enabled and disabled.Performance
H200, Qwen3.6 35B A3B NVFP4, MTP N=3, paired same-binary A/B:
expandInputRowslaunches per decoding step.Testing
lintrunner -aon the five changed files.moe_gemv_fp4.cuandmoe_quantization.ccagainst the exact [CUDA] Speed up the NVFP4 QMoE decode GEMV and enable it for MTP verify #31159 head.Checklist