[Bugfix] Size and iterate w13 by shard count for non-gated MoE (#51125)

Signed-off-by: aoshen02 <aoshen@inferact.ai> Co-authored-by: Matej Sirovatka <matej.sirovatka@gmail.com> Co-authored-by: Rishi Puri <riship@nvidia.com> Co-authored-by: Hsiao-Yuan Chen <littlecircle0730@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

aoshen02 committed Aug 6, 2026 at 08:24 UTC 7c77868cdf57c3f711ba971fa68d421b5b39a9c4
16 files changed +104 -80
tests/quantization/test_auto_gptq.py
+1
@@ -65,6 +65,7 @@ def test_auto_gptq_moe_creates_zero_initialized_expert_biases():
65 method.quant_config = AutoGPTQConfig(4, 128, False, True, False, {}, {})
66 method.input_dtype = None
67 method.experts_cls = None
68 + method.moe = SimpleNamespace(w13_num_shards=2)
69 layer = torch.nn.Module()
70
71 method.create_weights(
tests/quantization/test_auto_round.py
+4 -2
@@ -8,6 +8,7 @@ Validating the configuration and printing results for manual checking.
8 Run `pytest tests/quantization/test_auto_round.py`.
9 """
10
11 +from types import SimpleNamespace
12 from typing import Any, cast
13
14 import pytest
@@ -694,7 +695,8 @@ def test_inc_mxfp4_moe_method_registers_weights_and_builds_kernel(
695 INCMxfp4MoEMethod,
696 )
697
697 - method = INCMxfp4MoEMethod(moe=cast(Any, "moe-config"))
698 + expected_moe_config = SimpleNamespace(w13_num_shards=2)
699 + method = INCMxfp4MoEMethod(moe=cast(Any, expected_moe_config))
700 layer = torch.nn.Module()
701 layer._expert_routing_tables = lambda: "routing-tables"
702
@@ -723,7 +725,7 @@ def test_inc_mxfp4_moe_method_registers_weights_and_builds_kernel(
725 assert captured["quant_config_kwargs"]["w1_scale"] is layer.w13_weight_scale
726 assert captured["quant_config_kwargs"]["w2_scale"] is layer.w2_weight_scale
727 assert captured["kernel_kwargs"]["moe_quant_config"] is expected_quant_config
726 - assert captured["kernel_kwargs"]["moe_config"] == "moe-config"
728 + assert captured["kernel_kwargs"]["moe_config"] is expected_moe_config
729 assert captured["kernel_kwargs"]["experts_cls"] is expected_experts_cls
730 assert captured["kernel_kwargs"]["routing_tables"] == "routing-tables"
731 assert method.moe_kernel is expected_kernel
vllm/model_executor/layers/fused_moe/config.py
+5
@@ -1375,6 +1375,11 @@ class FusedMoEConfig:
1375 def is_act_and_mul(self) -> bool:
1376 return self.activation.is_gated
1377
1378 + @property
1379 + def w13_num_shards(self) -> int:
1380 + """Number of shards fused into w13: gate and up for gated, up only."""
1381 + return 2 if self.is_act_and_mul else 1
1382 +
1383 @property
1384 def tp_size(self):
1385 return self.moe_parallel_config.tp_size
vllm/model_executor/layers/quantization/auto_awq.py
+7 -3
@@ -592,7 +592,9 @@ class AutoAWQMoEMethod(FusedMoEMethodBase):
592 torch.empty(
593 num_experts,
594 hidden_size,
595 - 2 * intermediate_size_per_partition // self.quant_config.pack_factor,
595 + self.moe.w13_num_shards
596 + * intermediate_size_per_partition
597 + // self.quant_config.pack_factor,
598 dtype=torch.int32,
599 ),
600 requires_grad=False,
@@ -623,7 +625,7 @@ class AutoAWQMoEMethod(FusedMoEMethodBase):
625 torch.empty(
626 num_experts,
627 num_groups_w13,
626 - intermediate_size_per_partition * 2,
628 + intermediate_size_per_partition * self.moe.w13_num_shards,
629 dtype=params_dtype,
630 ),
631 requires_grad=False,
@@ -644,7 +646,9 @@ class AutoAWQMoEMethod(FusedMoEMethodBase):
646 torch.empty(
647 num_experts,
648 num_groups_w13,
647 - 2 * intermediate_size_per_partition // self.quant_config.pack_factor,
649 + self.moe.w13_num_shards
650 + * intermediate_size_per_partition
651 + // self.quant_config.pack_factor,
652 dtype=torch.int32,
653 ),
654 requires_grad=False,
vllm/model_executor/layers/quantization/auto_gptq.py
+6 -4
@@ -541,7 +541,7 @@ class AutoGPTQMoEMethod(FusedMoEMethodBase):
541 torch.empty(
542 num_experts,
543 hidden_size // self.quant_config.pack_factor,
544 - 2 * intermediate_size_per_partition,
544 + self.moe.w13_num_shards * intermediate_size_per_partition,
545 dtype=torch.int32,
546 ),
547 requires_grad=False,
@@ -565,7 +565,7 @@ class AutoGPTQMoEMethod(FusedMoEMethodBase):
565 torch.empty(
566 num_experts,
567 scales_size13,
568 - 2 * intermediate_size_per_partition,
568 + self.moe.w13_num_shards * intermediate_size_per_partition,
569 dtype=params_dtype,
570 ),
571 requires_grad=False,
@@ -586,7 +586,9 @@ class AutoGPTQMoEMethod(FusedMoEMethodBase):
586 torch.empty(
587 num_experts,
588 scales_size13,
589 - 2 * intermediate_size_per_partition // self.quant_config.pack_factor,
589 + self.moe.w13_num_shards
590 + * intermediate_size_per_partition
591 + // self.quant_config.pack_factor,
592 dtype=torch.int32,
593 ),
594 requires_grad=False,
@@ -654,7 +656,7 @@ class AutoGPTQMoEMethod(FusedMoEMethodBase):
656 w13_bias = torch.nn.Parameter(
657 torch.zeros(
658 num_experts,
657 - 2 * intermediate_size_per_partition,
659 + self.moe.w13_num_shards * intermediate_size_per_partition,
660 dtype=params_dtype,
661 ),
662 requires_grad=False,
vllm/model_executor/layers/quantization/bitsandbytes.py
+3 -3
@@ -523,7 +523,7 @@ class BitsAndBytesMoEMethod(FusedMoEMethodBase):
523 quant_ratio = calculate_quant_ratio(params_dtype)
524 # Fused gate_up_proj (column parallel)
525 w13_total_size = (
526 - hidden_size * 2 * intermediate_size_per_partition
526 + hidden_size * self.moe.w13_num_shards * intermediate_size_per_partition
527 ) // quant_ratio
528 w13_qweight = torch.nn.Parameter(
529 torch.empty(
@@ -541,10 +541,10 @@ class BitsAndBytesMoEMethod(FusedMoEMethodBase):
541 {
542 "num_experts": num_experts,
543 "input_dim": hidden_size,
544 - "output_dim": 2 * intermediate_size_per_partition,
544 + "output_dim": self.moe.w13_num_shards * intermediate_size_per_partition,
545 "experts_shape": (
546 num_experts,
547 - intermediate_size_per_partition * 2,
547 + intermediate_size_per_partition * self.moe.w13_num_shards,
548 hidden_size,
549 ),
550 "pack_factor": quant_ratio,
vllm/model_executor/layers/quantization/compressed_tensors/compressed_tensors_moe/compressed_tensors_moe_w4a4_mxfp4.py
+2 -2
@@ -75,7 +75,7 @@ class CompressedTensorsW4A4Mxfp4MoEMethod(CompressedTensorsMoEMethod):
75 w13_weight = torch.nn.Parameter(
76 torch.empty(
77 num_experts,
78 - 2 * intermediate_size_per_partition,
78 + self.moe.w13_num_shards * intermediate_size_per_partition,
79 # 2 fp4 items are packed in the input dimension
80 hidden_size // 2,
81 requires_grad=False,
@@ -102,7 +102,7 @@ class CompressedTensorsW4A4Mxfp4MoEMethod(CompressedTensorsMoEMethod):
102 w13_weight_scale = torch.nn.Parameter(
103 torch.empty(
104 num_experts,
105 - 2 * intermediate_size_per_partition,
105 + self.moe.w13_num_shards * intermediate_size_per_partition,
106 # 2 fp4 items are packed in the input dimension
107 hidden_size // self.group_size,
108 dtype=torch.uint8,
vllm/model_executor/layers/quantization/compressed_tensors/compressed_tensors_moe/compressed_tensors_moe_w4a8_fp8.py
+3 -3
@@ -79,7 +79,7 @@ class CompressedTensorsW4A8Fp8MoEMethod(CompressedTensorsMoEMethod):
79 w13_weight_packed = torch.nn.Parameter(
80 torch.empty(
81 num_experts,
82 - 2 * intermediate_size_per_partition,
82 + self.moe.w13_num_shards * intermediate_size_per_partition,
83 hidden_size // self.packed_factor,
84 dtype=params_dtype,
85 ),
@@ -107,7 +107,7 @@ class CompressedTensorsW4A8Fp8MoEMethod(CompressedTensorsMoEMethod):
107 w13_weight_scale = torch.nn.Parameter(
108 torch.ones(
109 num_experts,
110 - 2 * intermediate_size_per_partition,
110 + self.moe.w13_num_shards * intermediate_size_per_partition,
111 hidden_size // self.group_size,
112 dtype=layer.orig_dtype,
113 ),
@@ -147,7 +147,7 @@ class CompressedTensorsW4A8Fp8MoEMethod(CompressedTensorsMoEMethod):
147 w13_weight_chan_scale = torch.nn.Parameter(
148 torch.ones(
149 num_experts,
150 - 2 * intermediate_size_per_partition,
150 + self.moe.w13_num_shards * intermediate_size_per_partition,
151 dtype=torch.float32,
152 ),
153 requires_grad=False,
vllm/model_executor/layers/quantization/fp8.py
+12 -5
@@ -545,7 +545,7 @@ class Fp8MoEMethod(FusedMoEMethodBase):
545 w13_weight = torch.nn.Parameter(
546 torch.empty(
547 num_experts,
548 - 2 * intermediate_size_per_partition,
548 + self.moe.w13_num_shards * intermediate_size_per_partition,
549 hidden_size,
550 dtype=params_dtype,
551 ),
@@ -571,7 +571,7 @@ class Fp8MoEMethod(FusedMoEMethodBase):
571 w13_bias = torch.nn.Parameter(
572 torch.zeros(
573 num_experts,
574 - 2 * intermediate_size_per_partition,
574 + self.moe.w13_num_shards * intermediate_size_per_partition,
575 dtype=layer.orig_dtype,
576 ),
577 requires_grad=False,
@@ -588,13 +588,16 @@ class Fp8MoEMethod(FusedMoEMethodBase):
588 # WEIGHT_SCALES
589 if not self.block_quant:
590 # For per-tensor quant, the scales are per expert and weight.
591 - w13_scale_data = torch.ones(num_experts, 2, dtype=torch.float32)
591 + w13_scale_data = torch.ones(
592 + num_experts, self.moe.w13_num_shards, dtype=torch.float32
593 + )
594 w2_scale_data = torch.ones(num_experts, dtype=torch.float32)
595 else:
596 # For block quant, the scales are per block (typically 128x128).
597 w13_scale_data = torch.ones(
598 num_experts,
597 - 2 * ((intermediate_size_per_partition + block_n - 1) // block_n),
599 + self.moe.w13_num_shards
600 + * ((intermediate_size_per_partition + block_n - 1) // block_n),
601 (hidden_size + block_k - 1) // block_k,
602 dtype=torch.float32,
603 )
@@ -722,7 +725,11 @@ class Fp8MoEMethod(FusedMoEMethodBase):
725 if not self.block_quant:
726 shard_size = layer.intermediate_size_per_partition
727 w13, w13_scale = process_fp8_weight_tensor_strategy_moe(
725 - w13, w13_scale, shard_size, layer.local_num_experts
728 + w13,
729 + w13_scale,
730 + shard_size,
731 + layer.local_num_experts,
732 + is_act_and_mul=self.moe.is_act_and_mul,
733 )
734
735 # Shuffle weights to runtime format and setup kernel.
vllm/model_executor/layers/quantization/humming.py
+2 -2
@@ -728,10 +728,10 @@ class HummingMoEMethod(FusedMoEMethodBase):
728 # The weight names of sublayer start with the prefix "{sublayer_name}_"
729 layer.sublayer_configs = {
730 "w13": {
731 - "shape_n": intermediate_size_per_partition * 2,
731 + "shape_n": intermediate_size_per_partition * self.moe.w13_num_shards,
732 "shape_k": hidden_size,
733 "tensors_attrs": self.weight_schema.get_padded_tensors_attrs(
734 - shape_n=intermediate_size_per_partition * 2,
734 + shape_n=intermediate_size_per_partition * self.moe.w13_num_shards,
735 shape_k=hidden_size,
736 num_experts=num_experts,
737 param_dtype=params_dtype,
vllm/model_executor/layers/quantization/inc/schemes/inc_mxfp4_moe.py
+2 -2
@@ -88,7 +88,7 @@ class INCMxfp4MoEMethod(FusedMoEMethodBase):
88 w13_weight = torch.nn.Parameter(
89 torch.empty(
90 num_experts,
91 - 2 * intermediate_size_per_partition,
91 + self.moe.w13_num_shards * intermediate_size_per_partition,
92 hidden_size // 2,
93 dtype=torch.uint8,
94 ),
@@ -113,7 +113,7 @@ class INCMxfp4MoEMethod(FusedMoEMethodBase):
113 w13_weight_scale = torch.nn.Parameter(
114 torch.empty(
115 num_experts,
116 - 2 * intermediate_size_per_partition,
116 + self.moe.w13_num_shards * intermediate_size_per_partition,
117 hidden_size // self.group_size,
118 dtype=torch.uint8,
119 ),
vllm/model_executor/layers/quantization/moe_wna16.py
+5 -3
@@ -276,7 +276,7 @@ class MoeWNA16Method(FusedMoEMethodBase):
276 w13_qweight = torch.nn.Parameter(
277 torch.empty(
278 num_experts,
279 - 2 * intermediate_size_per_partition,
279 + self.moe.w13_num_shards * intermediate_size_per_partition,
280 hidden_size // bit8_pack_factor,
281 dtype=torch.uint8,
282 ),
@@ -301,7 +301,7 @@ class MoeWNA16Method(FusedMoEMethodBase):
301 w13_scales = torch.nn.Parameter(
302 torch.zeros(
303 num_experts,
304 - 2 * intermediate_size_per_partition,
304 + self.moe.w13_num_shards * intermediate_size_per_partition,
305 hidden_size // group_size,
306 dtype=params_dtype,
307 ),
@@ -326,7 +326,9 @@ class MoeWNA16Method(FusedMoEMethodBase):
326 w13_qzeros = torch.nn.Parameter(
327 torch.zeros(
328 num_experts,
329 - 2 * intermediate_size_per_partition // bit8_pack_factor,
329 + self.moe.w13_num_shards
330 + * intermediate_size_per_partition
331 + // bit8_pack_factor,
332 hidden_size // group_size,
333 dtype=torch.uint8,
334 ),
vllm/model_executor/layers/quantization/mxfp4.py
+12 -12
@@ -215,7 +215,7 @@ class GptOssMxfp4MoEMethod(FusedMoEMethodBase):
215 w13_weight = torch.nn.Parameter(
216 torch.zeros(
217 num_experts,
218 - 2 * intermediate_size_per_partition,
218 + self.moe.w13_num_shards * intermediate_size_per_partition,
219 hidden_size // 2,
220 dtype=weight_dtype,
221 ),
@@ -227,7 +227,7 @@ class GptOssMxfp4MoEMethod(FusedMoEMethodBase):
227 w13_weight_scale = torch.nn.Parameter(
228 torch.zeros(
229 num_experts,
230 - 2 * intermediate_size_per_partition,
230 + self.moe.w13_num_shards * intermediate_size_per_partition,
231 hidden_size // mxfp4_block,
232 dtype=scale_dtype,
233 ),
@@ -267,7 +267,7 @@ class GptOssMxfp4MoEMethod(FusedMoEMethodBase):
267 w13_bias = torch.nn.Parameter(
268 torch.zeros(
269 num_experts,
270 - 2 * intermediate_size_per_partition,
270 + self.moe.w13_num_shards * intermediate_size_per_partition,
271 dtype=torch.bfloat16,
272 ),
273 requires_grad=False,
@@ -305,13 +305,13 @@ class GptOssMxfp4MoEMethod(FusedMoEMethodBase):
305 assert (
306 w13.dim() == 3
307 and w13.shape[0] == num_experts
308 - and w13.shape[1] == intermediate_size * 2
308 + and w13.shape[1] == intermediate_size * self.moe.w13_num_shards
309 and w13.shape[2] == hidden_size // 2
310 )
311 assert (
312 w13_scale.dim() == 3
313 and w13_scale.shape[0] == num_experts
314 - and w13_scale.shape[1] == intermediate_size * 2
314 + and w13_scale.shape[1] == intermediate_size * self.moe.w13_num_shards
315 and w13_scale.shape[2] == hidden_size // sf_block_size
316 )
317 assert (
@@ -329,7 +329,7 @@ class GptOssMxfp4MoEMethod(FusedMoEMethodBase):
329 assert (
330 w13_bias.dim() == 2
331 and w13_bias.shape[0] == num_experts
332 - and w13_bias.shape[1] == intermediate_size * 2
332 + and w13_bias.shape[1] == intermediate_size * self.moe.w13_num_shards
333 )
334 if w2_bias is not None:
335 assert (
@@ -599,7 +599,7 @@ class Mxfp4MoEMethod(FusedMoEMethodBase):
599 w13_weight = torch.nn.Parameter(
600 torch.zeros(
601 num_experts,
602 - 2 * intermediate_size_per_partition,
602 + self.moe.w13_num_shards * intermediate_size_per_partition,
603 hidden_size // 2,
604 dtype=weight_dtype,
605 ),
@@ -611,7 +611,7 @@ class Mxfp4MoEMethod(FusedMoEMethodBase):
611 w13_weight_scale = torch.nn.Parameter(
612 torch.zeros(
613 num_experts,
614 - 2 * intermediate_size_per_partition,
614 + self.moe.w13_num_shards * intermediate_size_per_partition,
615 hidden_size // mxfp4_block,
616 dtype=scale_dtype,
617 ),
@@ -651,7 +651,7 @@ class Mxfp4MoEMethod(FusedMoEMethodBase):
651 w13_bias = torch.nn.Parameter(
652 torch.zeros(
653 num_experts,
654 - 2 * intermediate_size_per_partition,
654 + self.moe.w13_num_shards * intermediate_size_per_partition,
655 dtype=torch.bfloat16,
656 ),
657 requires_grad=False,
@@ -689,13 +689,13 @@ class Mxfp4MoEMethod(FusedMoEMethodBase):
689 assert (
690 w13.dim() == 3
691 and w13.shape[0] == num_experts
692 - and w13.shape[1] == intermediate_size * 2
692 + and w13.shape[1] == intermediate_size * self.moe.w13_num_shards
693 and w13.shape[2] == hidden_size // 2
694 )
695 assert (
696 w13_scale.dim() == 3
697 and w13_scale.shape[0] == num_experts
698 - and w13_scale.shape[1] == intermediate_size * 2
698 + and w13_scale.shape[1] == intermediate_size * self.moe.w13_num_shards
699 and w13_scale.shape[2] == hidden_size // sf_block_size
700 )
701 assert (
@@ -713,7 +713,7 @@ class Mxfp4MoEMethod(FusedMoEMethodBase):
713 assert (
714 w13_bias.dim() == 2
715 and w13_bias.shape[0] == num_experts
716 - and w13_bias.shape[1] == intermediate_size * 2
716 + and w13_bias.shape[1] == intermediate_size * self.moe.w13_num_shards
717 )
718 if w2_bias is not None:
719 assert (
vllm/model_executor/layers/quantization/online/fp8.py
+10 -12
@@ -582,12 +582,11 @@ class Fp8PerBlockOnlineMoEMethod(_Fp8OnlineMoEBase):
582 hidden_size = layer.moe_config.hidden_dim_unpadded
583 intermediate_size = layer.moe_config.intermediate_size_per_partition_unpadded
584
585 - w13_half_size = layer.w13_weight.shape[1] // 2
586 - if w13_half_size > intermediate_size:
587 - layer.w13_weight[:, intermediate_size:w13_half_size, :] = 0
588 - layer.w13_weight[
589 - :, w13_half_size + intermediate_size : 2 * w13_half_size, :
590 - ] = 0
585 + w13_shard = layer.w13_weight.shape[1] // self.moe.w13_num_shards
586 + if w13_shard > intermediate_size:
587 + for shard in range(self.moe.w13_num_shards):
588 + start = shard * w13_shard + intermediate_size
589 + layer.w13_weight[:, start : (shard + 1) * w13_shard, :] = 0
590 if layer.w13_weight.shape[2] > hidden_size:
591 layer.w13_weight[:, :, hidden_size:] = 0
592
@@ -597,12 +596,11 @@ class Fp8PerBlockOnlineMoEMethod(_Fp8OnlineMoEBase):
596 layer.w2_weight[:, :, intermediate_size:] = 0
597
598 if getattr(layer, "w13_bias", None) is not None:
600 - w13_bias_half_size = layer.w13_bias.shape[1] // 2
601 - if w13_bias_half_size > intermediate_size:
602 - layer.w13_bias[:, intermediate_size:w13_bias_half_size] = 0
603 - layer.w13_bias[
604 - :, w13_bias_half_size + intermediate_size : 2 * w13_bias_half_size
605 - ] = 0
599 + w13_bias_shard = layer.w13_bias.shape[1] // self.moe.w13_num_shards
600 + if w13_bias_shard > intermediate_size:
601 + for shard in range(self.moe.w13_num_shards):
602 + start = shard * w13_bias_shard + intermediate_size
603 + layer.w13_bias[:, start : (shard + 1) * w13_bias_shard] = 0
604
605 if (
606 getattr(layer, "w2_bias", None) is not None
vllm/model_executor/layers/quantization/online/moe_base.py
+2 -2
@@ -40,7 +40,7 @@ class OnlineMoEMethodBase(FusedMoEMethodBase):
40 w13_weight = torch.nn.Parameter(
41 torch.empty(
42 num_experts,
43 - 2 * intermediate_size_per_partition,
43 + self.moe.w13_num_shards * intermediate_size_per_partition,
44 hidden_size,
45 device="meta",
46 dtype=params_dtype,
@@ -69,7 +69,7 @@ class OnlineMoEMethodBase(FusedMoEMethodBase):
69 w13_bias = torch.nn.Parameter(
70 torch.zeros(
71 num_experts,
72 - 2 * intermediate_size_per_partition,
72 + self.moe.w13_num_shards * intermediate_size_per_partition,
73 device="meta",
74 dtype=layer.orig_dtype,
75 ),
vllm/model_executor/layers/quantization/quark/quark_moe.py
+28 -25
@@ -216,7 +216,7 @@ class QuarkW8A8Fp8MoEMethod(QuarkMoEMethod):
216 w13_weight = torch.nn.Parameter(
217 torch.zeros(
218 num_experts,
219 - 2 * intermediate_size_per_partition,
219 + self.moe.w13_num_shards * intermediate_size_per_partition,
220 hidden_size,
221 dtype=params_dtype,
222 ),
@@ -243,7 +243,10 @@ class QuarkW8A8Fp8MoEMethod(QuarkMoEMethod):
243 # They are combined to a single scale after weight loading.
244 if self.model_type != "gpt_oss":
245 w13_weight_scale = torch.nn.Parameter(
246 - torch.ones(num_experts, 2, dtype=torch.float32), requires_grad=False
246 + torch.ones(
247 + num_experts, self.moe.w13_num_shards, dtype=torch.float32
248 + ),
249 + requires_grad=False,
250 )
251 else:
252 # For gpt_oss, the w1(gate) & w3(up) are fused as one.
@@ -267,7 +270,7 @@ class QuarkW8A8Fp8MoEMethod(QuarkMoEMethod):
270 w13_weight_scale = torch.nn.Parameter(
271 torch.ones(
272 num_experts,
270 - 2 * intermediate_size_per_partition,
273 + self.moe.w13_num_shards * intermediate_size_per_partition,
274 dtype=torch.float32,
275 ),
276 requires_grad=False,
@@ -306,7 +309,7 @@ class QuarkW8A8Fp8MoEMethod(QuarkMoEMethod):
309 w13_bias = torch.nn.Parameter(
310 torch.zeros(
311 num_experts,
309 - 2 * intermediate_size_per_partition,
312 + self.moe.w13_num_shards * intermediate_size_per_partition,
313 dtype=torch.float32,
314 ),
315 requires_grad=False,
@@ -400,7 +403,7 @@ class QuarkW8A8Fp8MoEMethod(QuarkMoEMethod):
403 # For non-gpt_oss, process w1 and w3 shards separately
404 for expert_id in range(layer.local_num_experts):
405 start = 0
403 - for shard_id in range(2):
406 + for shard_id in range(self.moe.w13_num_shards):
407 dq_weight = per_tensor_dequantize(
408 layer.w13_weight[expert_id][start : start + shard_size, :],
409 layer.w13_weight_scale[expert_id][shard_id],
@@ -560,7 +563,7 @@ class QuarkW8A8Int8MoEMethod(QuarkMoEMethod):
563 w13_weight = torch.nn.Parameter(
564 torch.empty(
565 num_experts,
563 - 2 * intermediate_size_per_partition,
566 + self.moe.w13_num_shards * intermediate_size_per_partition,
567 hidden_size,
568 dtype=params_dtype,
569 ),
@@ -586,7 +589,7 @@ class QuarkW8A8Int8MoEMethod(QuarkMoEMethod):
589 w13_weight_scale = torch.nn.Parameter(
590 torch.ones(
591 num_experts,
589 - 2 * intermediate_size_per_partition,
592 + self.moe.w13_num_shards * intermediate_size_per_partition,
593 dtype=torch.float32,
594 ),
595 requires_grad=False,
@@ -605,7 +608,7 @@ class QuarkW8A8Int8MoEMethod(QuarkMoEMethod):
608 else:
609 # per-tensor: one scalar per expert (two for the fused w1/w3)
610 w13_weight_scale = torch.nn.Parameter(
608 - torch.ones(num_experts, 2, dtype=torch.float32),
611 + torch.ones(num_experts, self.moe.w13_num_shards, dtype=torch.float32),
612 requires_grad=False,
613 )
614 layer.register_parameter("w13_weight_scale", w13_weight_scale)
@@ -644,7 +647,7 @@ class QuarkW8A8Int8MoEMethod(QuarkMoEMethod):
647
648 # ZERO POINTS (loaded but discarded after loading; kernel uses symmetric)
649 w13_input_zero_point = torch.nn.Parameter(
647 - torch.zeros(num_experts, 2, dtype=torch.int8),
650 + torch.zeros(num_experts, self.moe.w13_num_shards, dtype=torch.int8),
651 requires_grad=False,
652 )
653 layer.register_parameter("w13_input_zero_point", w13_input_zero_point)
@@ -661,7 +664,7 @@ class QuarkW8A8Int8MoEMethod(QuarkMoEMethod):
664 w13_weight_zero_point = torch.nn.Parameter(
665 torch.zeros(
666 num_experts,
664 - 2 * intermediate_size_per_partition,
667 + self.moe.w13_num_shards * intermediate_size_per_partition,
668 dtype=torch.int8,
669 ),
670 requires_grad=False,
@@ -672,7 +675,7 @@ class QuarkW8A8Int8MoEMethod(QuarkMoEMethod):
675 )
676 else:
677 w13_weight_zero_point = torch.nn.Parameter(
675 - torch.zeros(num_experts, 2, dtype=torch.int8),
678 + torch.zeros(num_experts, self.moe.w13_num_shards, dtype=torch.int8),
679 requires_grad=False,
680 )
681 w2_weight_zero_point = torch.nn.Parameter(
@@ -689,7 +692,7 @@ class QuarkW8A8Int8MoEMethod(QuarkMoEMethod):
692 w13_bias = torch.nn.Parameter(
693 torch.zeros(
694 num_experts,
692 - 2 * intermediate_size_per_partition,
695 + self.moe.w13_num_shards * intermediate_size_per_partition,
696 dtype=torch.float32,
697 ),
698 requires_grad=False,
@@ -762,7 +765,7 @@ class QuarkW8A8Int8MoEMethod(QuarkMoEMethod):
765
766 for expert_id in range(layer.local_num_experts):
767 start = 0
765 - for shard_id in range(2):
768 + for shard_id in range(self.moe.w13_num_shards):
769 dq_weight = per_tensor_dequantize(
770 layer.w13_weight[expert_id][start : start + shard_size, :],
771 layer.w13_weight_scale[expert_id][shard_id],
@@ -905,7 +908,7 @@ class QuarkW4A8Fp8MoEMethod(QuarkMoEMethod):
908 w13_weight = torch.nn.Parameter(
909 torch.zeros(
910 num_experts,
908 - 2 * intermediate_size_per_partition,
911 + self.moe.w13_num_shards * intermediate_size_per_partition,
912 hidden_size // 8, # INT32 packing for W4
913 dtype=params_dtype,
914 ),
@@ -927,7 +930,8 @@ class QuarkW4A8Fp8MoEMethod(QuarkMoEMethod):
930
931 # Per-tensor fp8 weight scales
932 w13_weight_scale = torch.nn.Parameter(
930 - torch.ones(num_experts, 2, dtype=torch.float32), requires_grad=False
933 + torch.ones(num_experts, self.moe.w13_num_shards, dtype=torch.float32),
934 + requires_grad=False,
935 )
936 w2_weight_scale = torch.nn.Parameter(
937 torch.ones(num_experts, dtype=torch.float32), requires_grad=False
@@ -944,7 +948,7 @@ class QuarkW4A8Fp8MoEMethod(QuarkMoEMethod):
948 w13_weight_scale_2 = torch.nn.Parameter(
949 torch.ones(
950 num_experts,
947 - 2 * intermediate_size_per_partition,
951 + self.moe.w13_num_shards * intermediate_size_per_partition,
952 dtype=torch.float32,
953 ),
954 requires_grad=False,
@@ -978,7 +982,7 @@ class QuarkW4A8Fp8MoEMethod(QuarkMoEMethod):
982 for expert_id in range(layer.local_num_experts):
983 start = 0
984 max_w13_scale_fp8 = max_w13_scales[expert_id]
981 - for shard_id in range(2):
985 + for shard_id in range(self.moe.w13_num_shards):
986 if layer.w13_weight_scale[expert_id][shard_id] != max_w13_scale_fp8:
987 int4_rescale = (
988 layer.w13_weight_scale[expert_id][shard_id] / max_w13_scale_fp8
@@ -1193,7 +1197,7 @@ class QuarkOCP_MX_MoEMethod(QuarkMoEMethod):
1197 w13_weight = torch.nn.Parameter(
1198 torch.zeros(
1199 num_experts,
1196 - 2 * intermediate_size_per_partition,
1200 + self.moe.w13_num_shards * intermediate_size_per_partition,
1201 self.get_packed_dim(hidden_size, self.weight_dtype),
1202 dtype=params_dtype,
1203 ),
@@ -1220,7 +1224,7 @@ class QuarkOCP_MX_MoEMethod(QuarkMoEMethod):
1224 w13_weight_scale = torch.nn.Parameter(
1225 torch.ones(
1226 num_experts,
1223 - 2 * intermediate_size_per_partition,
1227 + self.moe.w13_num_shards * intermediate_size_per_partition,
1228 hidden_size // OCP_MX_BLOCK_SIZE,
1229 dtype=params_dtype,
1230 ),
@@ -1245,7 +1249,7 @@ class QuarkOCP_MX_MoEMethod(QuarkMoEMethod):
1249 w13_bias = torch.nn.Parameter(
1250 torch.zeros(
1251 num_experts,
1248 - 2 * intermediate_size_per_partition,
1252 + self.moe.w13_num_shards * intermediate_size_per_partition,
1253 dtype=torch.float32,
1254 ),
1255 requires_grad=False,
@@ -1499,13 +1503,12 @@ class QuarkNvfp4MoEMethod(QuarkMoEMethod):
1503 layer.quant_config = self.quant_config
1504 weight_dtype = torch.uint8
1505 weight_scale_dtype = torch.float8_e4m3fn
1502 - w13_num_shards = 2 if self.moe.is_act_and_mul else 1
1506
1507 # GEMM 1 - w13 weight
1508 w13_weight = torch.nn.Parameter(
1509 torch.empty(
1510 num_experts,
1508 - w13_num_shards * intermediate_size_per_partition,
1511 + self.moe.w13_num_shards * intermediate_size_per_partition,
1512 # 2 fp4 items are packed in the input dimension
1513 hidden_size // 2,
1514 dtype=weight_dtype,
@@ -1533,7 +1536,7 @@ class QuarkNvfp4MoEMethod(QuarkMoEMethod):
1536 w13_weight_scale = torch.nn.Parameter(
1537 torch.empty(
1538 num_experts,
1536 - w13_num_shards * intermediate_size_per_partition,
1539 + self.moe.w13_num_shards * intermediate_size_per_partition,
1540 hidden_size // self.group_size,
1541 dtype=weight_scale_dtype,
1542 ),
@@ -1563,7 +1566,7 @@ class QuarkNvfp4MoEMethod(QuarkMoEMethod):
1566 )
1567
1568 w13_weight_scale_2 = torch.nn.Parameter(
1566 - torch.empty(num_experts, w13_num_shards, dtype=torch.float32),
1569 + torch.empty(num_experts, self.moe.w13_num_shards, dtype=torch.float32),
1570 requires_grad=False,
1571 )
1572 layer.register_parameter("w13_weight_scale_2", w13_weight_scale_2)
@@ -1578,7 +1581,7 @@ class QuarkNvfp4MoEMethod(QuarkMoEMethod):
1581
1582 # Input global scales (per-tensor FP32 scales)
1583 w13_input_scale_2 = torch.nn.Parameter(
1581 - torch.empty(num_experts, w13_num_shards, dtype=torch.float32),
1584 + torch.empty(num_experts, self.moe.w13_num_shards, dtype=torch.float32),
1585 requires_grad=False,
1586 )
1587 layer.register_parameter("w13_input_scale_2", w13_input_scale_2)