Gpt_oss prefill: avoid packed expert-axis slicing in chunked MoE to restore MXFP6 constant compression - #1165
Conversation
Signed-off-by: Abhishek kumar singh <sabhis@qti.qualcomm.com>
|
@abhishek-singh591 what tests are verified on this? Disaggregated mode example? |
Yes i tested this till compile of prefill+chunking since the changes were only made on the prefill part, didn't check the Perf. |
Signed-off-by: abhishek-singh591 <sabhis@qti.qualcomm.com>
|
QPC size went down from 37Gb to 17GB for full model with 4TS. Perf with 2 layer:- Perf before:- decode tok/sec=83.26760350742597 Perf after:- decode tok/sec=80.18426492513731. |
Signed-off-by: Abhishek Kumar Singh <sabhis@qti.qualcomm.com>
Signed-off-by: abhishek-singh591 <sabhis@qti.qualcomm.com>
Signed-off-by: Abhishek Kumar Singh <sabhis@qti.qualcomm.com>
| def _ensure_blocked_expert_weights(self, num_nsp: int) -> None: | ||
| """Rebuild blocked expert tensors when NSP partitioning changes.""" | ||
| num_experts = self.experts.num_experts | ||
| local_experts = num_experts // num_nsp | ||
| expected_wg_shape = (num_nsp, local_experts) | ||
|
|
||
| has_blocked_weights = all(hasattr(self, name) for name in ("W_g", "W_u", "W_d", "b_g", "b_u", "b_d")) | ||
| if has_blocked_weights and self.W_g.shape[:2] == expected_wg_shape: | ||
| return | ||
|
|
||
| # Ensure split gate/up aliases exist before blocked views are materialized. | ||
| if not hasattr(self.experts, "gate_proj") and hasattr(self.experts, "__qeff_init__"): | ||
| self.experts.__qeff_init__() | ||
| self.expert_blocking_num_nsp = num_nsp | ||
| self.__qeff_init__() |
There was a problem hiding this comment.
why is this needed, shouldn't qeff_init always run and do this? is this check really needed?
There was a problem hiding this comment.
Yes just added in the readme, expert_blocking_num_nsp is set after transform in the test, and GPT-OSS blocked tensors (W_g/W_u/W_d, b_g/b_u/b_d) are shape-dependent on that value.
So, Without re-init, tensors stay in old layout (usually initialized with default num_nsp=num_experts), so matmul/add hits axis mismatch later. The disagg failure (a=16 vs b=32) is exactly that: runtime used num_nsp=16 while blocked params were still built for num_nsp=32.
This removes the need for manual __qeff_init__() calls in tests when only expert-blocking attrs are changed.
There was a problem hiding this comment.
Then, this layout rewrite should be called outside before export, and not in forward method.
There was a problem hiding this comment.
But that would require updating all the test files. We also need to handle cases where export is called multiple times with expert_blocking_num_nsp, since subsequent export calls could fail due to the modified code. So, this logic should probably live in the model file itself, though not necessarily inside the forward() method.
|
Closing this as it is part of MOE transform PR #1190. |
Root cause and fix summary (prefill-only)
Before (problematic pattern)
In
QEffPrefillOnlyChunkedGptOssMLP.forward, the prefill path did:W_g/W_u/W_dand biases were reshaped to[num_nsp, local_experts, ...].local_slotloop:W_g[:, local_slot],W_u[:, local_slot], etc.This matches the compiler pattern we observed:
float16<16 x 2 x 2880 x 2880>0and1)So even with logically split gate/up params, this path reintroduced a packed-then-sliced representation during subfunction export.
After (fixed pattern)
The updated code now:
routing_weights_by_expert = routing_weights.transpose(0, 1)→[num_experts, T]local_slot:slot_start = local_slot * num_nspslot_end = slot_start + num_nspself.experts.gate_proj[slot_start:slot_end]self.experts.up_proj[slot_start:slot_end]self.experts.down_proj[slot_start:slot_end]So we no longer materialize
[num_nsp, local_experts, ...]temporaries and no longer slice that axis inside the subfunction body.Fix implemented
GPT-OSS chunked MLP now auto-rebuilds blocked tensors whenever
expert_blocking_num_nspchanges:_ensure_blocked_expert_weights(num_nsp)inQEfficient/transformers/models/gpt_oss/modeling_gpt_oss.py.forward()before blocked MoE compute.This removes the need for manual
__qeff_init__()calls in tests when only expert-blocking attrs are changed.