Introducing OptimizedMoeTransform - #1190
Conversation
|
|
||
| hidden_states = hidden_states + self.shared_experts(residuals) | ||
| return hidden_states | ||
| QEffPrefillChunkedGlm4MoeMoE = QEffGlm4MoeMoE |
| if hasattr(self.experts, "gate_up_proj"): | ||
| self.moe_weights = build_canonical_expert_weights( | ||
| gate_up=self.experts.gate_up_proj, | ||
| down=self.experts.down_proj, | ||
| fused=True, | ||
| fused_split_dim=1, | ||
| transpose_gate_up=True, | ||
| transpose_down=True, | ||
| ) | ||
| delete_module_attrs(self.experts, "gate_up_proj", "down_proj") | ||
| else: |
There was a problem hiding this comment.
this if-else is not needed, as we always know what weights model is going to have, let's fix it instead of handling un-necessary cases.
| order = torch.argsort(out, dim=1) | ||
| last_positions = order[:, -state_len:] |
| mask_causal = torch.ones(chunk_size, chunk_size, dtype=torch.bool) | ||
| for i in range(chunk_size): | ||
| for j in range(i, chunk_size): | ||
| mask_causal[i, j] = True | ||
| for j in range(i + 1): | ||
| mask_causal[i, j] = False |
| g = g.reshape(g.shape[0], g.shape[1], -1, chunk_size) | ||
| # mask = torch.triu(torch.ones(chunk_size, chunk_size, dtype=torch.bool, device=query.device), diagonal=0) | ||
| mask = mask_causal | ||
| mask = mask_causal.to(device=query.device) |
|
TODO: allow cores_per_expert to be fraction |
| if kv_cache_prefix: | ||
| kwargs["kv_cache_prefix"] = kv_cache_prefix | ||
|
|
||
| num_devices = int(compiler_options.pop("num_devices", 1)) |
There was a problem hiding this comment.
nit: any specific reason why we are popping the num_devices? similar to how we take the num_cores we can use get right?
| qaic_config=qaic_config, | ||
| prefill_only=prefill_only, | ||
| enable_chunking=enable_chunking, | ||
| num_cores=kwargs.get("num_cores", compiler_options.get("aic_num_cores", constants.DEFAULT_AIC_NUM_CORES)), |
There was a problem hiding this comment.
variables are not added to transfrom method, in the transform method is still fetching the num_cores from compiler args.
| self.hash_params["qaic_config"] = qaic_config | ||
| self.hash_params["num_replicate_kv_heads"] = effective_num_replicate_kv_heads | ||
|
|
||
| num_cores = compiler_options.get("num_cores", compiler_options.get("aic_num_cores")) |
There was a problem hiding this comment.
num_cores, prefill_seq, prefill_only length is passed as arguments. Need not extrat it again.
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
Signed-off-by: ochougul <ochougul@qti.qualcomm.com>
07007f5 to
718b8e2
Compare
This PR standardizes QEff MoE model wrappers around a single explicit
QEffMoEBlockMixin contract.
Key changes:
Enforces every QEffMoEBlockMixin subclass to explicitly declare
supported_moe_flavours.
Collapses DeepSeek V3 MoE into a single QEffDeepseekV3MoE block and
removes the separate prefill-only class.
Adds explicit MoE flavour declarations for DeepSeek V3 and Grok1.
Introduces a single Gemma4 text MoE block backed by QEffMoEBlockMixin.
Updates external MoE mapper wiring to source support metadata from the
QEff block classes.
Removes Gemma4’s prefill-only expert mapping in favor of the shared MoE
flavour path.
Impact For New MoE Models
When adding a new MoE model, the model should expose one QEff MoE block that
inherits QEffMoEBlockMixin and explicitly declares:
supported_moe_flavours = (...)
The block should implement the common variation points:
This keeps flavour selection, export config, and future optimizations
centralized instead of spreading model-specific prefill/decode paths across
multiple classes.
Future Scope
The longer-term direction is to support all MoE flavours across all MoE
models where the model architecture allows it, especially:
This PR makes that easier by making supported flavour declarations explicit
and discoverable.
Tests
Added/updated coverage for:
Validation run:
pytest tests/transformers/models/test_moe_prefill_blocked.py -k 'moe_block
or deepseek or grok or gemma4'
pytest tests/unit_test/transforms/test_transform_accuracy.py -k
'OptimizedMoE or deepseek or external_mapper'
pytest tests/unit_test/models/test_model_quickcheck.py -k 'moe_prefill'