Repository navigation
Document and test packed token inputs for MoE and QMoE - #32522
Conversation
There was a problem hiding this comment.
π‘ Changes recommended
The new MoE cases cannot construct their graphs, routing differs from the reference, CPU tests may silently pass, and generated docs are stale.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Documents and tests packed token-major inputs for CPU/CUDA MoE and QMoE.
Changes:
- Clarifies packed-input schemas and provider documentation.
- Adds CPU and CUDA parity tests.
- Corrects CPU routing-input selection.
File summaries
| File | Description |
|---|---|
contrib_defs.cc |
Updates MoE/QMoE schemas. |
moe_qmoe.md |
Documents CUDA packed inputs. |
qmoe.md |
Documents CPU packed inputs. |
test_qmoe_cpu.py |
Adds CPU tests and routing fix. |
test_qmoe_cuda.py |
Adds CUDA tests. |
Review details
Suppressed comments (3)
onnxruntime/test/python/transformers/test_qmoe_cpu.py:1471
- The new
quant_bits=0case cannot construct this fixture.PhiMoESparseMoeBlockkeeps float expert weights whenquant_bits == 0, butcreate_cpu_moe_onnx_graphunconditionally asserts at lines 423-426 that both weights areuint8and scales are present. Guard those QMoE-only assertions withuse_quantso the intended MoE case can run.
@parameterized.expand([(0,), (4,)])
onnxruntime/test/python/transformers/test_qmoe_cuda.py:1593
- After the graph-builder assertions are fixed, the new MoE (
quant_bits=0) case still compares different routing algorithms:ort_forwardusesmasked_sampling_omp_inference(lines 765-782), whereasPhiMoESparseMoeBlock.forwarduses a softmax over the top-k logits. These weights differ for ordinary non-tied logits, so this parity test will fail for routing rather than validating packed input. Generate the MoE router tensor with the same top-k softmax as the reference.
packed_moe.parity_check()
onnxruntime/test/python/transformers/test_qmoe_cpu.py:1486
- This CPU test can pass without executing either operator:
parity_check()silently returns when model recreation fails (lines 1072-1074) or ORT execution returnsNone(lines 1078-1081), while those helpers catch session/run exceptions. Make these paths raise/assert, as the CUDA helper already does, so this test actually guarantees packed-input coverage.
packed_moe.parity_check()
- Files reviewed: 5/5 changed files
- Comments generated: 3
- Review effort level: Balanced
π‘ Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Preserve the constructor-created CUDA MoE session for the unquantized packed-input test and remove unrelated CPU scheduling, allocation, and CUDA fused-dispatch changes from this documentation and parity-test PR. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Copilot review overview
π‘ Changes recommended
The new non-quantized CUDA parity case applies softmax twice and therefore tests incorrect routing semantics.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
Open (2)
Feed raw router logits to both CUDA MoE test paths and enable kernel top-k normalization, avoiding the previous double-softmax mismatch in the unquantized packed-input parity case. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Ti-Tai Wang (titaiwangms)
left a comment
There was a problem hiding this comment.
The documented packed-token contract is consistent with the existing CPU/CUDA input validation, so I am approving.
Non-blocking test suggestion: the new test_packed_token_input_* cases still use the same flattened 2-D input path as the existing parity tests. A stronger regression test would compare padded 3-D input with concatenated packed input, ideally using sequences with different lengths, and assert token-for-token output parity. It would also be useful to retain coverage of normalize_routing_weights=0 in at least one case.



Description
Clarify and test packed token-major input support for the
MoEandQMoEoperators on the CPU and CUDA execution providers.
Packed inputs use:
[total_tokens, hidden_size][total_tokens, num_experts][total_tokens, hidden_size]Tokens from variable-length sequences can be concatenated without padding
because MoE routing is token-local and does not require sequence boundaries.
Changes
MoEandQMoEschema documentation.MoEand INT4QMoE.MoEand INT4QMoE.MoEwhile preserving raw router logits for
QMoE.No runtime kernel changes are required because the existing CPU and CUDA
implementations already process rank-2 token-major inputs.