A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 10, 11:30 UTC
[Misc][Refactor] Add FusedMoERouter object (#30519)
Signed-off-by: Bill Nell <bnell@redhat.com>
bnellnm committed
Jan 8, 2026 at 15:52 UTC
e74698c27ad5a66bb0f1b131a9e5582a0fbf00d1
20 files changed
+165
-36
tests/test_routing_simulator.py
+1
-1
@@ -127,7 +127,7 @@ def test_routing_strategy_integration(monkeypatch, device):
127
envs.environment_variables[env_name] = lambda s=strategy: s
128
129
# Test the select_experts method
130
- topk_weights, topk_ids = fused_moe.select_experts(
130
+ topk_weights, topk_ids = fused_moe.router.select_experts(
131
hidden_states=hidden_states,
132
router_logits=router_logits,
133
)
vllm/model_executor/layers/fused_moe/__init__.py
+4
@@ -11,6 +11,9 @@ from vllm.model_executor.layers.fused_moe.config import (
11
from vllm.model_executor.layers.fused_moe.fused_moe_method_base import (
12
FusedMoEMethodBase,
13
)
14
+from vllm.model_executor.layers.fused_moe.fused_moe_router import (
15
+ FusedMoERouter,
16
+)
17
from vllm.model_executor.layers.fused_moe.layer import (
18
FusedMoE,
19
FusedMoeWeightScaleSupported,
@@ -48,6 +51,7 @@ def get_config() -> dict[str, Any] | None:
51
52
__all__ = [
53
"FusedMoE",
54
+ "FusedMoERouter",
55
"FusedMoEConfig",
56
"FusedMoEMethodBase",
57
"UnquantizedFusedMoEMethod",
vllm/model_executor/layers/fused_moe/fused_moe_method_base.py
+4
@@ -10,6 +10,9 @@ from vllm.model_executor.layers.fused_moe.config import (
10
FusedMoEConfig,
11
FusedMoEQuantConfig,
12
)
13
+from vllm.model_executor.layers.fused_moe.fused_moe_router import (
14
+ FusedMoERouter,
15
+)
16
from vllm.model_executor.layers.fused_moe.modular_kernel import (
17
FusedMoEPermuteExpertsUnpermute,
18
FusedMoEPrepareAndFinalize,
@@ -109,6 +112,7 @@ class FusedMoEMethodBase(QuantizeMethodBase):
112
def apply(
113
self,
114
layer: "FusedMoE", # type: ignore[name-defined] # noqa: F821
115
+ router: FusedMoERouter,
116
x: torch.Tensor,
117
router_logits: torch.Tensor,
118
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
vllm/model_executor/layers/fused_moe/fused_moe_modular_method.py
+3
-1
@@ -12,6 +12,7 @@ from vllm.model_executor.layers.fused_moe.config import (
12
from vllm.model_executor.layers.fused_moe.fused_moe_method_base import (
13
FusedMoEMethodBase,
14
)
15
+from vllm.model_executor.layers.fused_moe.fused_moe_router import FusedMoERouter
16
from vllm.model_executor.layers.fused_moe.modular_kernel import (
17
FusedMoEModularKernel,
18
FusedMoEPrepareAndFinalize,
@@ -88,10 +89,11 @@ class FusedMoEModularMethod(FusedMoEMethodBase, CustomOp):
89
def apply(
90
self,
91
layer: "FusedMoE", # type: ignore[name-defined] # noqa: F821
92
+ router: FusedMoERouter,
93
x: torch.Tensor,
94
router_logits: torch.Tensor,
95
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
94
- topk_weights, topk_ids = layer.select_experts(
96
+ topk_weights, topk_ids = router.select_experts(
97
hidden_states=x,
98
router_logits=router_logits,
99
)
vllm/model_executor/layers/fused_moe/fused_moe_router.py
new
+40
@@ -0,0 +1,40 @@
1
+# SPDX-License-Identifier: Apache-2.0
2
+# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
+from abc import ABC, abstractmethod
4
+
5
+import torch
6
+
7
+from vllm.model_executor.layers.fused_moe.config import RoutingMethodType
8
+
9
+
10
+class FusedMoERouter(ABC):
11
+ """
12
+ FusedMoERouter is an abstract class that provides a 'select_experts'
13
+ method that is used for routing hidden states based on router logits.
14
+ """
15
+
16
+ @property
17
+ @abstractmethod
18
+ def routing_method_type(self) -> RoutingMethodType:
19
+ raise NotImplementedError
20
+
21
+ @abstractmethod
22
+ def select_experts(
23
+ self,
24
+ hidden_states: torch.Tensor,
25
+ router_logits: torch.Tensor,
26
+ ) -> tuple[torch.Tensor, torch.Tensor]:
27
+ """
28
+ Route the input hidden states to the top-k experts based on the
29
+ router logits.
30
+
31
+ Returns:
32
+ (topk_weights, topk_ids)
33
+ (tuple[torch.Tensor, torch.Tensor]):
34
+ The weights and expert ids computation result.
35
+
36
+ **Compatibility**: When EPLB is not enabled, the returned ids are
37
+ equivalent to global logical ids, so should be compatible with
38
+ plain MoE implementations without redundant experts.
39
+ """
40
+ raise NotImplementedError
vllm/model_executor/layers/fused_moe/layer.py
+25
-3
@@ -31,6 +31,7 @@ from vllm.model_executor.layers.fused_moe.config import (
31
FusedMoEQuantConfig,
32
RoutingMethodType,
33
)
34
+from vllm.model_executor.layers.fused_moe.fused_moe_router import FusedMoERouter
35
from vllm.model_executor.layers.fused_moe.rocm_aiter_fused_moe import (
36
init_aiter_topK_meta_data,
37
)
@@ -284,6 +285,23 @@ def maybe_roundup_hidden_size(
285
return hidden_size
286
287
288
+class FusedMoERouterImpl(FusedMoERouter):
289
+ def __init__(self, layer: "FusedMoE"):
290
+ super().__init__()
291
+ self.layer = layer
292
+
293
+ @property
294
+ def routing_method_type(self) -> RoutingMethodType:
295
+ return self.layer.routing_method_type
296
+
297
+ def select_experts(
298
+ self,
299
+ hidden_states: torch.Tensor,
300
+ router_logits: torch.Tensor,
301
+ ) -> tuple[torch.Tensor, torch.Tensor]:
302
+ return self.layer._select_experts(hidden_states, router_logits)
303
+
304
+
305
@CustomOp.register("fused_moe")
306
class FusedMoE(CustomOp):
307
"""FusedMoE layer for MoE models.
@@ -339,7 +357,7 @@ class FusedMoE(CustomOp):
357
is_sequence_parallel=False,
358
expert_mapping: list[tuple[str, str, int, str]] | None = None,
359
n_shared_experts: int | None = None,
342
- routing_method_type: int | None = None,
360
+ routing_method_type: RoutingMethodType | None = None,
361
router_logits_dtype: torch.dtype | None = None,
362
):
363
super().__init__()
@@ -529,7 +547,7 @@ class FusedMoE(CustomOp):
547
548
# ToDo: Better logic to determine the routing method type
549
if routing_method_type is not None:
532
- self.routing_method_type = routing_method_type
550
+ self.routing_method_type: RoutingMethodType = routing_method_type
551
else:
552
if scoring_func == "sigmoid":
553
if self.use_grouped_topk:
@@ -640,6 +658,8 @@ class FusedMoE(CustomOp):
658
self.batched_hidden_states: torch.Tensor | None = None
659
self.batched_router_logits: torch.Tensor | None = None
660
661
+ self.router = FusedMoERouterImpl(self)
662
+
663
# Note: maybe_init_modular_kernel should only be called by
664
# prepare_communication_buffer_for_model.
665
# This is called after all weight loading and post-processing, so it
@@ -1503,7 +1523,7 @@ class FusedMoE(CustomOp):
1523
device=torch.cuda.current_device(),
1524
)
1525
1506
- def select_experts(
1526
+ def _select_experts(
1527
self,
1528
hidden_states: torch.Tensor,
1529
router_logits: torch.Tensor,
@@ -1772,6 +1792,7 @@ class FusedMoE(CustomOp):
1792
# Matrix multiply.
1793
final_hidden_states = self.quant_method.apply(
1794
layer=self,
1795
+ router=self.router,
1796
x=staged_hidden_states,
1797
router_logits=staged_router_logits,
1798
)
@@ -1944,6 +1965,7 @@ class FusedMoE(CustomOp):
1965
# Matrix multiply.
1966
final_hidden_states = self.quant_method.apply(
1967
layer=self,
1968
+ router=self.router,
1969
x=hidden_states_combined
1970
if do_naive_dispatch_combine
1971
else hidden_states,
vllm/model_executor/layers/fused_moe/unquantized_fused_moe_method.py
+7
-1
@@ -22,6 +22,7 @@ from vllm.model_executor.layers.fused_moe.flashinfer_cutlass_moe import (
22
from vllm.model_executor.layers.fused_moe.fused_moe_method_base import (
23
FusedMoEMethodBase,
24
)
25
+from vllm.model_executor.layers.fused_moe.fused_moe_router import FusedMoERouter
26
from vllm.model_executor.layers.fused_moe.modular_kernel import (
27
FusedMoEActivationFormat,
28
FusedMoEPermuteExpertsUnpermute,
@@ -285,10 +286,12 @@ class UnquantizedFusedMoEMethod(FusedMoEMethodBase, CustomOp):
286
def apply(
287
self,
288
layer: "FusedMoE", # type: ignore[name-defined] # noqa: F821
289
+ router: FusedMoERouter,
290
x: torch.Tensor,
291
router_logits: torch.Tensor,
292
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
293
return self.forward(
294
+ router=router,
295
layer=layer,
296
x=x,
297
router_logits=router_logits,
@@ -306,10 +309,11 @@ class UnquantizedFusedMoEMethod(FusedMoEMethodBase, CustomOp):
309
def forward_cuda(
310
self,
311
layer: "FusedMoE", # type: ignore[name-defined] # noqa: F821
312
+ router: FusedMoERouter,
313
x: torch.Tensor,
314
router_logits: torch.Tensor,
315
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
312
- topk_weights, topk_ids = layer.select_experts(
316
+ topk_weights, topk_ids = router.select_experts(
317
hidden_states=x,
318
router_logits=router_logits,
319
)
@@ -332,6 +336,7 @@ class UnquantizedFusedMoEMethod(FusedMoEMethodBase, CustomOp):
336
def forward_cpu(
337
self,
338
layer: "FusedMoE", # type: ignore[name-defined] # noqa: F821
339
+ router: FusedMoERouter,
340
x: torch.Tensor,
341
router_logits: torch.Tensor,
342
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
@@ -365,6 +370,7 @@ class UnquantizedFusedMoEMethod(FusedMoEMethodBase, CustomOp):
370
def forward_xpu(
371
self,
372
layer: "FusedMoE", # type: ignore[name-defined] # noqa: F821
373
+ router: FusedMoERouter,
374
x: torch.Tensor,
375
router_logits: torch.Tensor,
376
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
vllm/model_executor/layers/quantization/awq_marlin.py
+3
-1
@@ -15,6 +15,7 @@ from vllm.model_executor.layers.fused_moe.config import (
15
FusedMoEQuantConfig,
16
)
17
from vllm.model_executor.layers.fused_moe.fused_marlin_moe import fused_marlin_moe
18
+from vllm.model_executor.layers.fused_moe.fused_moe_router import FusedMoERouter
19
from vllm.model_executor.layers.fused_moe.layer import (
20
FusedMoE,
21
FusedMoEMethodBase,
@@ -759,12 +760,13 @@ class AWQMarlinMoEMethod(FusedMoEMethodBase):
760
def apply(
761
self,
762
layer: FusedMoE,
763
+ router: FusedMoERouter,
764
x: torch.Tensor,
765
router_logits: torch.Tensor,
766
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
767
assert layer.activation == "silu", "Only SiLU activation is supported."
768
767
- topk_weights, topk_ids = layer.select_experts(
769
+ topk_weights, topk_ids = router.select_experts(
770
hidden_states=x,
771
router_logits=router_logits,
772
)
vllm/model_executor/layers/quantization/bitsandbytes.py
+7
-2
@@ -10,7 +10,11 @@ from vllm.model_executor.layers.fused_moe.config import (
10
FusedMoEConfig,
11
FusedMoEQuantConfig,
12
)
13
-from vllm.model_executor.layers.fused_moe.layer import FusedMoE, FusedMoEMethodBase
13
+from vllm.model_executor.layers.fused_moe.fused_moe_router import FusedMoERouter
14
+from vllm.model_executor.layers.fused_moe.layer import (
15
+ FusedMoE,
16
+ FusedMoEMethodBase,
17
+)
18
from vllm.model_executor.layers.linear import (
19
LinearBase,
20
LinearMethodBase,
@@ -495,12 +499,13 @@ class BitsAndBytesMoEMethod(FusedMoEMethodBase):
499
def apply(
500
self,
501
layer: FusedMoE,
502
+ router: FusedMoERouter,
503
x: torch.Tensor,
504
router_logits: torch.Tensor,
505
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
506
from vllm.model_executor.layers.fused_moe import fused_experts
507
503
- topk_weights, topk_ids = layer.select_experts(
508
+ topk_weights, topk_ids = router.select_experts(
509
hidden_states=x,
510
router_logits=router_logits,
511
)
vllm/model_executor/layers/quantization/compressed_tensors/compressed_tensors_moe.py
+14
-6
@@ -40,6 +40,7 @@ from vllm.model_executor.layers.fused_moe.fused_marlin_moe import (
40
MarlinExperts,
41
fused_marlin_moe,
42
)
43
+from vllm.model_executor.layers.fused_moe.fused_moe_router import FusedMoERouter
44
from vllm.model_executor.layers.fused_moe.oracle.fp8 import (
45
Fp8MoeBackend,
46
convert_to_fp8_moe_kernel_format,
@@ -458,6 +459,7 @@ class CompressedTensorsW4A4Nvfp4MoEMethod(CompressedTensorsMoEMethod):
459
def apply(
460
self,
461
layer: FusedMoE,
462
+ router: FusedMoERouter,
463
x: torch.Tensor,
464
router_logits: torch.Tensor,
465
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
@@ -484,7 +486,7 @@ class CompressedTensorsW4A4Nvfp4MoEMethod(CompressedTensorsMoEMethod):
486
x_routing, _ = x
487
else:
488
x_routing = x
487
- topk_weights, topk_ids = layer.select_experts(
489
+ topk_weights, topk_ids = router.select_experts(
490
hidden_states=x_routing,
491
router_logits=router_logits,
492
)
@@ -926,10 +928,11 @@ class CompressedTensorsW8A8Fp8MoEMethod(CompressedTensorsMoEMethod):
928
def apply(
929
self,
930
layer: FusedMoE,
931
+ router: FusedMoERouter,
932
x: torch.Tensor,
933
router_logits: torch.Tensor,
934
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
932
- topk_weights, topk_ids = layer.select_experts(
935
+ topk_weights, topk_ids = router.select_experts(
936
hidden_states=x,
937
router_logits=router_logits,
938
)
@@ -1066,12 +1069,13 @@ class CompressedTensorsW8A8Int8MoEMethod(CompressedTensorsMoEMethod):
1069
def apply(
1070
self,
1071
layer: FusedMoE,
1072
+ router: FusedMoERouter,
1073
x: torch.Tensor,
1074
router_logits: torch.Tensor,
1075
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
1076
from vllm.model_executor.layers.fused_moe import fused_experts
1077
1074
- topk_weights, topk_ids = layer.select_experts(
1078
+ topk_weights, topk_ids = router.select_experts(
1079
hidden_states=x,
1080
router_logits=router_logits,
1081
)
@@ -1426,6 +1430,7 @@ class CompressedTensorsWNA16MarlinMoEMethod(CompressedTensorsMoEMethod):
1430
def apply(
1431
self,
1432
layer: FusedMoE,
1433
+ router: FusedMoERouter,
1434
x: torch.Tensor,
1435
router_logits: torch.Tensor,
1436
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
@@ -1433,7 +1438,7 @@ class CompressedTensorsWNA16MarlinMoEMethod(CompressedTensorsMoEMethod):
1438
f"{layer.activation} not supported for Marlin MoE."
1439
)
1440
1436
- topk_weights, topk_ids = layer.select_experts(
1441
+ topk_weights, topk_ids = router.select_experts(
1442
hidden_states=x,
1443
router_logits=router_logits,
1444
)
@@ -1677,12 +1682,13 @@ class CompressedTensorsWNA16MoEMethod(CompressedTensorsMoEMethod):
1682
def apply(
1683
self,
1684
layer: FusedMoE,
1685
+ router: FusedMoERouter,
1686
x: torch.Tensor,
1687
router_logits: torch.Tensor,
1688
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
1689
from vllm.model_executor.layers.fused_moe import fused_experts
1690
1685
- topk_weights, topk_ids = layer.select_experts(
1691
+ topk_weights, topk_ids = router.select_experts(
1692
hidden_states=x,
1693
router_logits=router_logits,
1694
)
@@ -1978,6 +1984,7 @@ class CompressedTensorsW4A8Int8MoEMethod(CompressedTensorsMoEMethod):
1984
def apply(
1985
self,
1986
layer: FusedMoE,
1987
+ router: FusedMoERouter,
1988
x: torch.Tensor,
1989
router_logits: torch.Tensor,
1990
) -> torch.Tensor:
@@ -2290,6 +2297,7 @@ class CompressedTensorsW4A8Fp8MoEMethod(CompressedTensorsMoEMethod):
2297
def apply(
2298
self,
2299
layer: FusedMoE,
2300
+ router: FusedMoERouter,
2301
x: torch.Tensor,
2302
router_logits: torch.Tensor,
2303
):
@@ -2298,7 +2306,7 @@ class CompressedTensorsW4A8Fp8MoEMethod(CompressedTensorsMoEMethod):
2306
"EPLB not supported for `CompressedTensorsW4A8Fp8MoEMethod` yet."
2307
)
2308
assert self.moe_quant_config is not None
2301
- topk_weights, topk_ids = layer.select_experts(
2309
+ topk_weights, topk_ids = router.select_experts(
2310
hidden_states=x,
2311
router_logits=router_logits,
2312
)
vllm/model_executor/layers/quantization/experts_int8.py
+3
-1
@@ -15,6 +15,7 @@ from vllm.model_executor.layers.fused_moe.config import (
15
FusedMoEQuantConfig,
16
int8_w8a16_moe_quant_config,
17
)
18
+from vllm.model_executor.layers.fused_moe.fused_moe_router import FusedMoERouter
19
from vllm.model_executor.layers.linear import LinearBase, UnquantizedLinearMethod
20
from vllm.model_executor.layers.quantization import QuantizationMethods
21
from vllm.model_executor.layers.quantization.base_config import (
@@ -137,12 +138,13 @@ class ExpertsInt8MoEMethod(FusedMoEMethodBase):
138
def apply(
139
self,
140
layer: FusedMoE,
141
+ router: FusedMoERouter,
142
x: torch.Tensor,
143
router_logits: torch.Tensor,
144
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
145
from vllm.model_executor.layers.fused_moe import fused_experts
146
145
- topk_weights, topk_ids = layer.select_experts(
147
+ topk_weights, topk_ids = router.select_experts(
148
hidden_states=x,
149
router_logits=router_logits,
150
)
vllm/model_executor/layers/quantization/fp8.py
+3
-1
@@ -29,6 +29,7 @@ from vllm.model_executor.layers.fused_moe.config import (
29
FusedMoEQuantConfig,
30
RoutingMethodType,
31
)
32
+from vllm.model_executor.layers.fused_moe.fused_moe_router import FusedMoERouter
33
from vllm.model_executor.layers.fused_moe.layer import UnquantizedFusedMoEMethod
34
from vllm.model_executor.layers.fused_moe.oracle.fp8 import (
35
Fp8MoeBackend,
@@ -997,6 +998,7 @@ class Fp8MoEMethod(FusedMoEMethodBase):
998
def apply(
999
self,
1000
layer: FusedMoE,
1001
+ router: FusedMoERouter,
1002
x: torch.Tensor,
1003
router_logits: torch.Tensor,
1004
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
@@ -1051,7 +1053,7 @@ class Fp8MoEMethod(FusedMoEMethodBase):
1053
apply_router_weight_on_input=layer.apply_router_weight_on_input,
1054
)
1055
1054
- topk_weights, topk_ids = layer.select_experts(
1056
+ topk_weights, topk_ids = router.select_experts(
1057
hidden_states=x,
1058
router_logits=router_logits,
1059
)
vllm/model_executor/layers/quantization/gguf.py
+7
-2
@@ -16,7 +16,11 @@ from vllm.model_executor.layers.fused_moe.config import (
16
FusedMoEConfig,
17
FusedMoEQuantConfig,
18
)
19
-from vllm.model_executor.layers.fused_moe.layer import FusedMoE, FusedMoEMethodBase
19
+from vllm.model_executor.layers.fused_moe.fused_moe_router import FusedMoERouter
20
+from vllm.model_executor.layers.fused_moe.layer import (
21
+ FusedMoE,
22
+ FusedMoEMethodBase,
23
+)
24
from vllm.model_executor.layers.linear import (
25
LinearBase,
26
LinearMethodBase,
@@ -629,6 +633,7 @@ class GGUFMoEMethod(FusedMoEMethodBase):
633
def apply(
634
self,
635
layer: FusedMoE,
636
+ router: FusedMoERouter,
637
x: torch.Tensor,
638
router_logits: torch.Tensor,
639
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
@@ -639,7 +644,7 @@ class GGUFMoEMethod(FusedMoEMethodBase):
644
"fused GGUF MoE method."
645
)
646
642
- topk_weights, topk_ids = layer.select_experts(
647
+ topk_weights, topk_ids = router.select_experts(
648
hidden_states=x,
649
router_logits=router_logits,
650
)
vllm/model_executor/layers/quantization/gptq_marlin.py
+3
-1
@@ -15,6 +15,7 @@ from vllm.model_executor.layers.fused_moe.config import (
15
FusedMoEQuantConfig,
16
)
17
from vllm.model_executor.layers.fused_moe.fused_marlin_moe import fused_marlin_moe
18
+from vllm.model_executor.layers.fused_moe.fused_moe_router import FusedMoERouter
19
from vllm.model_executor.layers.fused_moe.layer import (
20
FusedMoE,
21
FusedMoEMethodBase,
@@ -895,12 +896,13 @@ class GPTQMarlinMoEMethod(FusedMoEMethodBase):
896
def apply(
897
self,
898
layer: FusedMoE,
899
+ router: FusedMoERouter,
900
x: torch.Tensor,
901
router_logits: torch.Tensor,
902
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
903
assert layer.activation == "silu", "Only SiLU activation is supported."
904
903
- topk_weights, topk_ids = layer.select_experts(
905
+ topk_weights, topk_ids = router.select_experts(
906
hidden_states=x,
907
router_logits=router_logits,
908
)
vllm/model_executor/layers/quantization/ipex_quant.py
+4
@@ -9,6 +9,9 @@ from torch.nn import Module
9
10
from vllm._ipex_ops import ipex_ops as ops
11
from vllm.model_executor.layers.fused_moe.config import FusedMoEQuantConfig
12
+from vllm.model_executor.layers.fused_moe.fused_moe_router import (
13
+ FusedMoERouter,
14
+)
15
from vllm.model_executor.layers.linear import (
16
LinearBase,
17
LinearMethodBase,
@@ -384,6 +387,7 @@ class XPUFp8MoEMethod(Fp8OnlineMoEMethod):
387
def apply(
388
self,
389
layer: torch.nn.Module,
390
+ router: FusedMoERouter,
391
x: torch.Tensor,
392
router_logits: torch.Tensor,
393
) -> torch.Tensor:
vllm/model_executor/layers/quantization/modelopt.py
+15
-8
@@ -14,8 +14,10 @@ from vllm._custom_ops import cutlass_scaled_fp4_mm, scaled_fp4_quant
14
from vllm.attention.layer import Attention
15
from vllm.logger import init_logger
16
from vllm.model_executor.layers.fused_moe.config import (
17
+ FusedMoEConfig,
18
FusedMoEQuantConfig,
19
)
20
+from vllm.model_executor.layers.fused_moe.fused_moe_router import FusedMoERouter
21
from vllm.model_executor.layers.fused_moe.layer import (
22
FusedMoE,
23
FusedMoEMethodBase,
@@ -200,7 +202,9 @@ class ModelOptQuantConfigBase(QuantizationConfig):
202
quant_method.marlin_input_dtype = get_marlin_input_dtype(prefix)
203
return quant_method
204
elif isinstance(layer, FusedMoE):
203
- quant_method = self.FusedMoEMethodCls(quant_config=self, layer=layer)
205
+ quant_method = self.FusedMoEMethodCls(
206
+ quant_config=self, moe_config=layer.moe_config
207
+ )
208
if getattr(quant_method, "backend", "") == "marlin":
209
quant_method.marlin_input_dtype = get_marlin_input_dtype(prefix)
210
return quant_method
@@ -720,14 +724,14 @@ class ModelOptFp8MoEMethod(FusedMoEMethodBase):
724
def __init__(
725
self,
726
quant_config: ModelOptFp8Config,
723
- layer: FusedMoE,
727
+ moe_config: FusedMoEConfig,
728
) -> None:
725
- super().__init__(layer.moe_config)
729
+ super().__init__(moe_config)
730
self.quant_config = quant_config
731
assert self.quant_config.is_checkpoint_fp8_serialized
732
self.fp8_backend = select_fp8_moe_backend(
733
block_quant=False,
730
- tp_size=layer.moe_parallel_config.tp_size,
734
+ tp_size=moe_config.moe_parallel_config.tp_size,
735
with_lora_support=self.moe.is_lora_enabled,
736
)
737
self.kernel: mk.FusedMoEModularKernel | None = None
@@ -935,6 +939,7 @@ class ModelOptFp8MoEMethod(FusedMoEMethodBase):
939
def apply(
940
self,
941
layer: FusedMoE,
942
+ router: FusedMoERouter,
943
x: torch.Tensor,
944
router_logits: torch.Tensor,
945
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
@@ -961,7 +966,8 @@ class ModelOptFp8MoEMethod(FusedMoEMethodBase):
966
apply_router_weight_on_input=layer.apply_router_weight_on_input,
967
)
968
964
- topk_weights, topk_ids = layer.select_experts(
969
+ # Expert selection
970
+ topk_weights, topk_ids = router.select_experts(
971
hidden_states=x,
972
router_logits=router_logits,
973
)
@@ -1325,9 +1331,9 @@ class ModelOptNvFp4FusedMoE(FusedMoEMethodBase):
1331
def __init__(
1332
self,
1333
quant_config: ModelOptNvFp4Config,
1328
- layer: FusedMoE,
1334
+ moe_config: FusedMoEConfig,
1335
) -> None:
1330
- super().__init__(layer.moe_config)
1336
+ super().__init__(moe_config)
1337
self.quant_config = quant_config
1338
self.nvfp4_backend = select_nvfp4_moe_backend()
1339
# TODO: move this type of check into the oracle.
@@ -1597,6 +1603,7 @@ class ModelOptNvFp4FusedMoE(FusedMoEMethodBase):
1603
def apply(
1604
self,
1605
layer: FusedMoE,
1606
+ router: FusedMoERouter,
1607
x: torch.Tensor,
1608
router_logits: torch.Tensor,
1609
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
@@ -1621,7 +1628,7 @@ class ModelOptNvFp4FusedMoE(FusedMoEMethodBase):
1628
x_routing, _ = x
1629
else:
1630
x_routing = x
1624
- topk_weights, topk_ids = layer.select_experts(
1631
+ topk_weights, topk_ids = router.select_experts(
1632
hidden_states=x_routing,
1633
router_logits=router_logits,
1634
)
vllm/model_executor/layers/quantization/moe_wna16.py
+3
-1
@@ -11,6 +11,7 @@ from vllm.model_executor.layers.fused_moe.config import (
11
int4_w4a16_moe_quant_config,
12
int8_w8a16_moe_quant_config,
13
)
14
+from vllm.model_executor.layers.fused_moe.fused_moe_router import FusedMoERouter
15
from vllm.model_executor.layers.fused_moe.layer import (
16
FusedMoE,
17
FusedMoEConfig,
@@ -364,13 +365,14 @@ class MoeWNA16Method(FusedMoEMethodBase):
365
def apply(
366
self,
367
layer: FusedMoE,
368
+ router: FusedMoERouter,
369
x: torch.Tensor,
370
router_logits: torch.Tensor,
371
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
372
from vllm.model_executor.layers.fused_moe import fused_experts
373
374
assert layer.activation == "silu", "Only SiLU activation is supported."
373
- topk_weights, topk_ids = layer.select_experts(
375
+ topk_weights, topk_ids = router.select_experts(
376
hidden_states=x,
377
router_logits=router_logits,
378
)
vllm/model_executor/layers/quantization/mxfp4.py
+6
-3
@@ -27,6 +27,7 @@ from vllm.model_executor.layers.fused_moe.fused_marlin_moe import (
27
MarlinExperts,
28
fused_marlin_moe,
29
)
30
+from vllm.model_executor.layers.fused_moe.fused_moe_router import FusedMoERouter
31
from vllm.model_executor.layers.fused_moe.gpt_oss_triton_kernels_moe import (
32
OAITritonExperts,
33
UnfusedOAITritonExperts,
@@ -891,6 +892,7 @@ class Mxfp4MoEMethod(FusedMoEMethodBase):
892
def apply(
893
self,
894
layer: FusedMoE,
895
+ router: FusedMoERouter,
896
x: torch.Tensor,
897
router_logits: torch.Tensor,
898
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
@@ -898,7 +900,7 @@ class Mxfp4MoEMethod(FusedMoEMethodBase):
900
raise NotImplementedError("EPLB is not supported for mxfp4")
901
902
if self.mxfp4_backend == Mxfp4Backend.MARLIN:
901
- topk_weights, topk_ids = layer.select_experts(
903
+ topk_weights, topk_ids = router.select_experts(
904
hidden_states=x,
905
router_logits=router_logits,
906
)
@@ -992,7 +994,7 @@ class Mxfp4MoEMethod(FusedMoEMethodBase):
994
):
995
from vllm.utils.flashinfer import flashinfer_cutlass_fused_moe
996
995
- topk_weights, topk_ids = layer.select_experts(
997
+ topk_weights, topk_ids = router.select_experts(
998
hidden_states=x,
999
router_logits=router_logits,
1000
)
@@ -1119,7 +1121,8 @@ class IpexMxfp4MoEMethod(Mxfp4MoEMethod):
1121
1122
def apply(
1123
self,
1122
- layer: torch.nn.Module,
1124
+ layer: FusedMoE,
1125
+ router: FusedMoERouter,
1126
x: torch.Tensor,
1127
router_logits: torch.Tensor,
1128
) -> torch.Tensor:
vllm/model_executor/layers/quantization/quark/quark_moe.py
+6
-2
@@ -13,6 +13,7 @@ from vllm.model_executor.layers.fused_moe import (
13
FusedMoE,
14
FusedMoEConfig,
15
FusedMoEMethodBase,
16
+ FusedMoERouter,
17
FusedMoeWeightScaleSupported,
18
)
19
from vllm.model_executor.layers.fused_moe.config import (
@@ -350,10 +351,11 @@ class QuarkW8A8Fp8MoEMethod(QuarkMoEMethod):
351
def apply(
352
self,
353
layer: FusedMoE,
354
+ router: FusedMoERouter,
355
x: torch.Tensor,
356
router_logits: torch.Tensor,
357
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
356
- topk_weights, topk_ids = layer.select_experts(
358
+ topk_weights, topk_ids = router.select_experts(
359
hidden_states=x,
360
router_logits=router_logits,
361
)
@@ -542,6 +544,7 @@ class QuarkW4A8Fp8MoEMethod(QuarkMoEMethod):
544
def apply(
545
self,
546
layer: FusedMoE,
547
+ router: FusedMoERouter,
548
x: torch.Tensor,
549
router_logits: torch.Tensor,
550
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
@@ -750,10 +753,11 @@ class QuarkOCP_MX_MoEMethod(QuarkMoEMethod):
753
def apply(
754
self,
755
layer: FusedMoE,
756
+ router: FusedMoERouter,
757
x: torch.Tensor,
758
router_logits: torch.Tensor,
759
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
756
- topk_weights, topk_ids = layer.select_experts(
760
+ topk_weights, topk_ids = router.select_experts(
761
hidden_states=x,
762
router_logits=router_logits,
763
)
vllm/model_executor/layers/quantization/rtn.py
+7
-2
@@ -15,7 +15,11 @@ from vllm.model_executor.layers.fused_moe.config import (
15
FusedMoEQuantConfig,
16
)
17
from vllm.model_executor.layers.fused_moe.fused_marlin_moe import fused_marlin_moe
18
-from vllm.model_executor.layers.fused_moe.layer import FusedMoE, FusedMoEMethodBase
18
+from vllm.model_executor.layers.fused_moe.fused_moe_router import FusedMoERouter
19
+from vllm.model_executor.layers.fused_moe.layer import (
20
+ FusedMoE,
21
+ FusedMoEMethodBase,
22
+)
23
from vllm.model_executor.layers.linear import (
24
LinearBase,
25
LinearMethodBase,
@@ -356,10 +360,11 @@ class RTNMoEMethod(FusedMoEMethodBase):
360
def apply(
361
self,
362
layer: FusedMoE,
363
+ router: FusedMoERouter,
364
x: torch.Tensor,
365
router_logits: torch.Tensor,
366
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
362
- topk_weights, topk_ids = layer.select_experts(
367
+ topk_weights, topk_ids = router.select_experts(
368
hidden_states=x,
369
router_logits=router_logits,
370
)