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 15, 02:15 UTC
[Misc] ModularKernel : Perform WeightAndReduce inside TritonExperts & DeepGemmExperts (#20725)
Signed-off-by: Varun Sundar Rabindranath <vsundarr@redhat.com> Co-authored-by: Varun Sundar Rabindranath <vsundarr@redhat.com>
Varun Sundar Rabindranath committed
Jul 15, 2025 at 01:17 UTC
c0569dbc82b5e945a77878190114d1b68027828b
9 files changed
+203
-157
vllm/model_executor/layers/fused_moe/batched_deep_gemm_moe.py
+2
@@ -260,6 +260,7 @@ class BatchedDeepGemmExperts(mk.FusedMoEPermuteExpertsUnpermute):
260
hidden_states: torch.Tensor,
261
w1: torch.Tensor,
262
w2: torch.Tensor,
263
+ topk_weights: torch.Tensor,
264
topk_ids: torch.Tensor,
265
activation: str,
266
global_num_experts: int,
@@ -273,6 +274,7 @@ class BatchedDeepGemmExperts(mk.FusedMoEPermuteExpertsUnpermute):
274
workspace13: torch.Tensor,
275
workspace2: torch.Tensor,
276
expert_tokens_meta: Optional[mk.ExpertTokensMetadata],
277
+ apply_router_weight_on_input: bool,
278
):
279
assert expert_tokens_meta is not None
280
expert_num_tokens = expert_tokens_meta.expert_num_tokens
vllm/model_executor/layers/fused_moe/batched_triton_or_deep_gemm_moe.py
+16
-24
@@ -129,30 +129,22 @@ class BatchedTritonOrDeepGemmExperts(mk.FusedMoEPermuteExpertsUnpermute):
129
return self.batched_triton_experts.workspace_shapes(
130
a, aq, M, N, K, topk, global_num_experts, local_num_experts)
131
132
- def apply(
133
- self,
134
- output: torch.Tensor,
135
- hidden_states: torch.Tensor,
136
- w1: torch.Tensor,
137
- w2: torch.Tensor,
138
- topk_ids: torch.Tensor,
139
- activation: str,
140
- global_num_experts: int,
141
- expert_map: Optional[torch.Tensor],
142
- w1_scale: Optional[torch.Tensor],
143
- w2_scale: Optional[torch.Tensor],
144
- w1_zp: Optional[torch.Tensor],
145
- w2_zp: Optional[torch.Tensor],
146
- a1q_scale: Optional[torch.Tensor],
147
- a2_scale: Optional[torch.Tensor],
148
- workspace13: torch.Tensor,
149
- workspace2: torch.Tensor,
150
- expert_tokens_meta: Optional[mk.ExpertTokensMetadata],
151
- ):
132
+ def apply(self, output: torch.Tensor, hidden_states: torch.Tensor,
133
+ w1: torch.Tensor, w2: torch.Tensor, topk_weights: torch.Tensor,
134
+ topk_ids: torch.Tensor, activation: str, global_num_experts: int,
135
+ expert_map: Optional[torch.Tensor],
136
+ w1_scale: Optional[torch.Tensor],
137
+ w2_scale: Optional[torch.Tensor], w1_zp: Optional[torch.Tensor],
138
+ w2_zp: Optional[torch.Tensor], a1q_scale: Optional[torch.Tensor],
139
+ a2_scale: Optional[torch.Tensor], workspace13: torch.Tensor,
140
+ workspace2: torch.Tensor,
141
+ expert_tokens_meta: Optional[mk.ExpertTokensMetadata],
142
+ apply_router_weight_on_input: bool):
143
experts = (self.batched_deep_gemm_experts
144
if self.allow_deep_gemm else self.batched_triton_experts)
145
assert experts is not None
155
- experts.apply(output, hidden_states, w1, w2, topk_ids, activation,
156
- global_num_experts, expert_map, w1_scale, w2_scale,
157
- w1_zp, w2_zp, a1q_scale, a2_scale, workspace13,
158
- workspace2, expert_tokens_meta)
146
+ experts.apply(output, hidden_states, w1, w2, topk_weights, topk_ids,
147
+ activation, global_num_experts, expert_map, w1_scale,
148
+ w2_scale, w1_zp, w2_zp, a1q_scale, a2_scale, workspace13,
149
+ workspace2, expert_tokens_meta,
150
+ apply_router_weight_on_input)
vllm/model_executor/layers/fused_moe/cutlass_moe.py
+11
-20
@@ -291,26 +291,17 @@ class CutlassExpertsFp8(mk.FusedMoEPermuteExpertsUnpermute):
291
return (workspace1, workspace2, output,
292
self.out_dtype if self.out_dtype is not None else a.dtype)
293
294
- def apply(
295
- self,
296
- output: torch.Tensor,
297
- hidden_states: torch.Tensor,
298
- w1: torch.Tensor,
299
- w2: torch.Tensor,
300
- topk_ids: torch.Tensor,
301
- activation: str,
302
- global_num_experts: int,
303
- expert_map: Optional[torch.Tensor],
304
- w1_scale: Optional[torch.Tensor],
305
- w2_scale: Optional[torch.Tensor],
306
- w1_zp: Optional[torch.Tensor],
307
- w2_zp: Optional[torch.Tensor],
308
- a1q_scale: Optional[torch.Tensor],
309
- a2_scale: Optional[torch.Tensor],
310
- workspace13: torch.Tensor,
311
- workspace2: torch.Tensor,
312
- expert_tokens_meta: Optional[mk.ExpertTokensMetadata],
313
- ):
294
+ def apply(self, output: torch.Tensor, hidden_states: torch.Tensor,
295
+ w1: torch.Tensor, w2: torch.Tensor, topk_weights: torch.Tensor,
296
+ topk_ids: torch.Tensor, activation: str, global_num_experts: int,
297
+ expert_map: Optional[torch.Tensor],
298
+ w1_scale: Optional[torch.Tensor],
299
+ w2_scale: Optional[torch.Tensor], w1_zp: Optional[torch.Tensor],
300
+ w2_zp: Optional[torch.Tensor], a1q_scale: Optional[torch.Tensor],
301
+ a2_scale: Optional[torch.Tensor], workspace13: torch.Tensor,
302
+ workspace2: torch.Tensor,
303
+ expert_tokens_meta: Optional[mk.ExpertTokensMetadata],
304
+ apply_router_weight_on_input: bool):
305
assert w1_zp is None, "w1_zp is not supported in CUTLASS MoE"
306
assert w2_zp is None, "w2_zp is not supported in CUTLASS MoE"
307
vllm/model_executor/layers/fused_moe/deep_gemm_moe.py
+21
-10
@@ -13,7 +13,7 @@ from vllm.model_executor.layers.fused_moe.moe_permute_unpermute import (
13
from vllm.model_executor.layers.fused_moe.prepare_finalize import (
14
MoEPrepareAndFinalizeNoEP)
15
from vllm.model_executor.layers.fused_moe.topk_weight_and_reduce import (
16
- TopKWeightAndReduceDelegate)
16
+ TopKWeightAndReduceContiguous, TopKWeightAndReduceNoOP)
17
from vllm.model_executor.layers.fused_moe.utils import _resize_cache
18
from vllm.model_executor.layers.quantization.utils.fp8_utils import (
19
per_token_group_quant_fp8)
@@ -90,8 +90,7 @@ class DeepGemmExperts(mk.FusedMoEPermuteExpertsUnpermute):
90
return True
91
92
def finalize_weight_and_reduce_impl(self) -> mk.TopKWeightAndReduce:
93
- # Let PrepareAndFinalize::finalize() decide the impl.
94
- return TopKWeightAndReduceDelegate()
93
+ return TopKWeightAndReduceNoOP()
94
95
def workspace_shapes(
96
self, a: torch.Tensor, aq: torch.Tensor, M: int, N: int, K: int,
@@ -104,9 +103,9 @@ class DeepGemmExperts(mk.FusedMoEPermuteExpertsUnpermute):
103
block_m = self.block_shape[0]
104
M_sum = (M * topk) + num_experts * (block_m - 1)
105
M_sum = round_up(M_sum, block_m)
107
- workspace1 = (M_sum, max(N * 2, K))
106
+ workspace1 = (M_sum, max(N // 2, K))
107
workspace2 = (M_sum, max(N, K))
109
- output = (M, topk, K)
108
+ output = (M, K)
109
return (workspace1, workspace2, output, a.dtype)
110
111
def apply(
@@ -115,6 +114,7 @@ class DeepGemmExperts(mk.FusedMoEPermuteExpertsUnpermute):
114
hidden_states: torch.Tensor,
115
w1: torch.Tensor,
116
w2: torch.Tensor,
117
+ topk_weights: torch.Tensor,
118
topk_ids: torch.Tensor,
119
activation: str,
120
global_num_experts: int,
@@ -128,11 +128,14 @@ class DeepGemmExperts(mk.FusedMoEPermuteExpertsUnpermute):
128
workspace13: torch.Tensor,
129
workspace2: torch.Tensor,
130
expert_tokens_meta: Optional[mk.ExpertTokensMetadata],
131
+ apply_router_weight_on_input: bool,
132
):
133
assert self.block_shape is not None
134
135
a1q = hidden_states
136
_, N, K = w1.size()
137
+ M, _ = output.size()
138
+ num_topk = topk_ids.size(1)
139
140
if global_num_experts == -1:
141
global_num_experts = w1.size(0)
@@ -159,11 +162,12 @@ class DeepGemmExperts(mk.FusedMoEPermuteExpertsUnpermute):
162
# Note: M_sum is different than the pre-permuted shape of a1q.
163
M_sum = a1q.size(0)
164
162
- mm1_out = _resize_cache(workspace13, (M_sum, N))
163
- act_out = _resize_cache(workspace2, (M_sum, N // 2))
164
- quant_out = _resize_cache(workspace13.view(dtype=torch.float8_e4m3fn),
165
+ mm1_out = _resize_cache(workspace2, (M_sum, N))
166
+ act_out = _resize_cache(workspace13, (M_sum, N // 2))
167
+ quant_out = _resize_cache(workspace2.view(dtype=torch.float8_e4m3fn),
168
(M_sum, N // 2))
166
- mm2_out = _resize_cache(workspace2, (M_sum, K))
169
+ mm2_out = _resize_cache(workspace13, (M_sum, K))
170
+ perm_out = _resize_cache(workspace2, (M * num_topk, K))
171
172
m_grouped_fp8_gemm_nt_contiguous((a1q, a1q_scale), (w1, w1_scale),
173
mm1_out, expert_ids)
@@ -179,7 +183,14 @@ class DeepGemmExperts(mk.FusedMoEPermuteExpertsUnpermute):
183
m_grouped_fp8_gemm_nt_contiguous((a2q, a2q_scale), (w2, w2_scale),
184
mm2_out, expert_ids)
185
182
- torch.index_select(mm2_out, 0, inv_perm, out=output.view((-1, K)))
186
+ torch.index_select(mm2_out, 0, inv_perm, out=perm_out)
187
+
188
+ TopKWeightAndReduceContiguous().apply(
189
+ output=output,
190
+ fused_expert_output=perm_out,
191
+ topk_weights=topk_weights,
192
+ topk_ids=topk_ids,
193
+ apply_router_weight_on_input=apply_router_weight_on_input)
194
195
196
def deep_gemm_moe_fp8(
vllm/model_executor/layers/fused_moe/fused_batched_moe.py
+8
-6
@@ -696,15 +696,16 @@ class NaiveBatchedExperts(mk.FusedMoEPermuteExpertsUnpermute):
696
return t.to(f32) * group_broadcast(scale, t.shape)
697
698
def apply(self, output: torch.Tensor, hidden_states: torch.Tensor,
699
- w1: torch.Tensor, w2: torch.Tensor, topk_ids: torch.Tensor,
700
- activation: str, global_num_experts: int,
699
+ w1: torch.Tensor, w2: torch.Tensor, topk_weights: torch.Tensor,
700
+ topk_ids: torch.Tensor, activation: str, global_num_experts: int,
701
expert_map: Optional[torch.Tensor],
702
w1_scale: Optional[torch.Tensor],
703
w2_scale: Optional[torch.Tensor], w1_zp: Optional[torch.Tensor],
704
w2_zp: Optional[torch.Tensor], a1q_scale: Optional[torch.Tensor],
705
a2_scale: Optional[torch.Tensor], workspace13: torch.Tensor,
706
workspace2: torch.Tensor,
707
- expert_tokens_meta: Optional[mk.ExpertTokensMetadata]):
707
+ expert_tokens_meta: Optional[mk.ExpertTokensMetadata],
708
+ apply_router_weight_on_input: bool):
709
assert hidden_states.dim() == 3
710
assert expert_tokens_meta is not None
711
expert_num_tokens = expert_tokens_meta.expert_num_tokens
@@ -899,15 +900,16 @@ class BatchedTritonExperts(mk.FusedMoEPermuteExpertsUnpermute):
900
return (workspace13, workspace2, output, a.dtype)
901
902
def apply(self, output: torch.Tensor, hidden_states: torch.Tensor,
902
- w1: torch.Tensor, w2: torch.Tensor, topk_ids: torch.Tensor,
903
- activation: str, global_num_experts: int,
903
+ w1: torch.Tensor, w2: torch.Tensor, topk_weights: torch.Tensor,
904
+ topk_ids: torch.Tensor, activation: str, global_num_experts: int,
905
expert_map: Optional[torch.Tensor],
906
w1_scale: Optional[torch.Tensor],
907
w2_scale: Optional[torch.Tensor], w1_zp: Optional[torch.Tensor],
908
w2_zp: Optional[torch.Tensor], a1q_scale: Optional[torch.Tensor],
909
a2_scale: Optional[torch.Tensor], workspace13: torch.Tensor,
910
workspace2: torch.Tensor,
910
- expert_tokens_meta: Optional[mk.ExpertTokensMetadata]):
911
+ expert_tokens_meta: Optional[mk.ExpertTokensMetadata],
912
+ apply_router_weight_on_input: bool):
913
# Check constraints.
914
if self.use_int4_w4a16:
915
assert hidden_states.size(-1) // 2 == w1.size(2), (
vllm/model_executor/layers/fused_moe/fused_moe.py
+38
-33
@@ -26,7 +26,7 @@ from vllm.model_executor.layers.fused_moe.moe_align_block_size import (
26
from vllm.model_executor.layers.fused_moe.prepare_finalize import (
27
MoEPrepareAndFinalizeNoEP)
28
from vllm.model_executor.layers.fused_moe.topk_weight_and_reduce import (
29
- TopKWeightAndReduceDelegate)
29
+ TopKWeightAndReduceNoOP)
30
from vllm.model_executor.layers.fused_moe.utils import (
31
_resize_cache, moe_kernel_quantize_input)
32
from vllm.model_executor.layers.quantization.utils.mxfp4_utils import (
@@ -1606,8 +1606,7 @@ class TritonExperts(mk.FusedMoEPermuteExpertsUnpermute):
1606
return True
1607
1608
def finalize_weight_and_reduce_impl(self) -> mk.TopKWeightAndReduce:
1609
- # Let PrepareAndFinalize::finalize() decide the impl.
1610
- return TopKWeightAndReduceDelegate()
1609
+ return TopKWeightAndReduceNoOP()
1610
1611
def workspace_shapes(
1612
self,
@@ -1620,9 +1619,9 @@ class TritonExperts(mk.FusedMoEPermuteExpertsUnpermute):
1619
global_num_experts: int,
1620
local_num_experts: int,
1621
) -> tuple[tuple[int, ...], tuple[int, ...], tuple[int, ...], torch.dtype]:
1623
- workspace1 = (M, topk, max(N * 2, K))
1624
- workspace2 = (M, topk, N)
1625
- output = (M, topk, K)
1622
+ workspace1 = (M, topk, max(N // 2, K))
1623
+ workspace2 = (M, topk, max(N, K))
1624
+ output = (M, K)
1625
return (workspace1, workspace2, output, a.dtype)
1626
1627
def apply(
@@ -1631,6 +1630,7 @@ class TritonExperts(mk.FusedMoEPermuteExpertsUnpermute):
1630
hidden_states: torch.Tensor,
1631
w1: torch.Tensor,
1632
w2: torch.Tensor,
1633
+ topk_weights: torch.Tensor,
1634
topk_ids: torch.Tensor,
1635
activation: str,
1636
global_num_experts: int,
@@ -1644,6 +1644,7 @@ class TritonExperts(mk.FusedMoEPermuteExpertsUnpermute):
1644
workspace13: torch.Tensor,
1645
workspace2: torch.Tensor,
1646
expert_tokens_meta: Optional[mk.ExpertTokensMetadata],
1647
+ apply_router_weight_on_input: bool,
1648
):
1649
# Check constraints.
1650
if self.use_int4_w4a16:
@@ -1696,37 +1697,39 @@ class TritonExperts(mk.FusedMoEPermuteExpertsUnpermute):
1697
raise ValueError(
1698
f"Unsupported compute_type: {hidden_states.dtype}")
1699
1699
- # We can reuse the memory between these because by the time we need
1700
- # cache3, we're done with cache1
1701
- intermediate_cache1 = _resize_cache(workspace13,
1700
+ # Note that the output tensor might be in workspace1
1701
+ intermediate_cache1 = _resize_cache(workspace2,
1702
(num_tokens, top_k_num, N))
1703
- intermediate_cache2 = _resize_cache(workspace2,
1703
+ intermediate_cache2 = _resize_cache(workspace13,
1704
(num_tokens * top_k_num, N // 2))
1705
+ intermediate_cache3 = _resize_cache(workspace2,
1706
+ (num_tokens, top_k_num, K))
1707
1708
sorted_token_ids, expert_ids, num_tokens_post_padded = (
1709
moe_align_block_size(topk_ids, config['BLOCK_SIZE_M'],
1710
global_num_experts, expert_map))
1711
1710
- invoke_fused_moe_kernel(hidden_states,
1711
- w1,
1712
- intermediate_cache1,
1713
- a1q_scale,
1714
- w1_scale,
1715
- w1_zp,
1716
- None,
1717
- sorted_token_ids,
1718
- expert_ids,
1719
- num_tokens_post_padded,
1720
- False,
1721
- top_k_num,
1722
- config,
1723
- compute_type=compute_type,
1724
- use_fp8_w8a8=self.use_fp8_w8a8,
1725
- use_int8_w8a8=self.use_int8_w8a8,
1726
- use_int8_w8a16=self.use_int8_w8a16,
1727
- use_int4_w4a16=self.use_int4_w4a16,
1728
- per_channel_quant=self.per_act_token_quant,
1729
- block_shape=self.block_shape)
1712
+ invoke_fused_moe_kernel(
1713
+ hidden_states,
1714
+ w1,
1715
+ intermediate_cache1,
1716
+ a1q_scale,
1717
+ w1_scale,
1718
+ w1_zp,
1719
+ None, # topk_weights
1720
+ sorted_token_ids,
1721
+ expert_ids,
1722
+ num_tokens_post_padded,
1723
+ False, # mul_routed_weights
1724
+ top_k_num,
1725
+ config,
1726
+ compute_type=compute_type,
1727
+ use_fp8_w8a8=self.use_fp8_w8a8,
1728
+ use_int8_w8a8=self.use_int8_w8a8,
1729
+ use_int8_w8a16=self.use_int8_w8a16,
1730
+ use_int4_w4a16=self.use_int4_w4a16,
1731
+ per_channel_quant=self.per_act_token_quant,
1732
+ block_shape=self.block_shape)
1733
1734
self.activation(activation, intermediate_cache2,
1735
intermediate_cache1.view(-1, N))
@@ -1739,15 +1742,15 @@ class TritonExperts(mk.FusedMoEPermuteExpertsUnpermute):
1742
1743
invoke_fused_moe_kernel(qintermediate_cache2,
1744
w2,
1742
- output,
1745
+ intermediate_cache3,
1746
a2q_scale,
1747
w2_scale,
1748
w2_zp,
1746
- None,
1749
+ topk_weights,
1750
sorted_token_ids,
1751
expert_ids,
1752
num_tokens_post_padded,
1750
- False,
1753
+ not apply_router_weight_on_input,
1754
1,
1755
config,
1756
compute_type=compute_type,
@@ -1758,6 +1761,8 @@ class TritonExperts(mk.FusedMoEPermuteExpertsUnpermute):
1761
per_channel_quant=self.per_act_token_quant,
1762
block_shape=self.block_shape)
1763
1764
+ ops.moe_sum(intermediate_cache3, output)
1765
+
1766
1767
def modular_triton_fused_moe(
1768
use_fp8_w8a8: bool,
vllm/model_executor/layers/fused_moe/modular_kernel.py
+91
-59
@@ -360,6 +360,7 @@ class FusedMoEPermuteExpertsUnpermute(ABC):
360
hidden_states: torch.Tensor,
361
w1: torch.Tensor,
362
w2: torch.Tensor,
363
+ topk_weights: torch.Tensor,
364
topk_ids: torch.Tensor,
365
activation: str,
366
global_num_experts: int,
@@ -373,6 +374,7 @@ class FusedMoEPermuteExpertsUnpermute(ABC):
374
workspace13: torch.Tensor,
375
workspace2: torch.Tensor,
376
expert_tokens_meta: Optional[ExpertTokensMetadata],
377
+ apply_router_weight_on_input: bool,
378
):
379
"""
380
This function computes the intermediate result of a Mixture of Experts
@@ -384,6 +386,8 @@ class FusedMoEPermuteExpertsUnpermute(ABC):
386
layer.
387
- w1 (torch.Tensor): The first set of expert weights.
388
- w2 (torch.Tensor): The second set of expert weights.
389
+ - topk_weights: A map of row to expert weights. Some implementations
390
+ choose to do weight application.
391
- topk_ids (torch.Tensor): A map of row to expert id.
392
- activation (str): The activation function to apply after the first
393
MoE layer.
@@ -409,6 +413,9 @@ class FusedMoEPermuteExpertsUnpermute(ABC):
413
ExpertTokensMetadata object containing gpu/cpu tensors
414
as big as the number of local experts with the information about the
415
number of tokens assigned to each local expert.
416
+ - apply_router_weight_on_input: True if router weights are already
417
+ applied on the input. This is relevant if the implementation
418
+ chooses to do weight application.
419
"""
420
raise NotImplementedError
421
@@ -452,17 +459,21 @@ class FusedMoEModularKernel(torch.nn.Module):
459
f"{fused_experts.__class__.__name__}."
460
f"{fused_experts.activation_formats[0]}")
461
455
- def _do_fused_experts(
456
- self, fused_out: Optional[torch.Tensor], a1: torch.Tensor,
457
- a1q: torch.Tensor, w1: torch.Tensor, w2: torch.Tensor,
458
- topk_ids: torch.Tensor, activation: str, global_num_experts: int,
459
- local_num_experts: int, expert_map: Optional[torch.Tensor],
460
- w1_scale: Optional[torch.Tensor], w2_scale: Optional[torch.Tensor],
461
- w1_zp: Optional[torch.Tensor], w2_zp: Optional[torch.Tensor],
462
- a1q_scale: Optional[torch.Tensor],
463
- a2_scale: Optional[torch.Tensor],
464
- expert_tokens_meta: Optional[ExpertTokensMetadata]
465
- ) -> torch.Tensor:
462
+ def _do_fused_experts(self, fused_out: Optional[torch.Tensor],
463
+ a1: torch.Tensor, a1q: torch.Tensor,
464
+ w1: torch.Tensor, w2: torch.Tensor,
465
+ topk_weights: torch.Tensor, topk_ids: torch.Tensor,
466
+ activation: str, global_num_experts: int,
467
+ local_num_experts: int,
468
+ expert_map: Optional[torch.Tensor],
469
+ w1_scale: Optional[torch.Tensor],
470
+ w2_scale: Optional[torch.Tensor],
471
+ w1_zp: Optional[torch.Tensor],
472
+ w2_zp: Optional[torch.Tensor],
473
+ a1q_scale: Optional[torch.Tensor],
474
+ a2_scale: Optional[torch.Tensor],
475
+ expert_tokens_meta: Optional[ExpertTokensMetadata],
476
+ apply_router_weight_on_input: bool) -> torch.Tensor:
477
478
_, M, N, K, top_k = _moe_problem_size(a1q, w1, w2, topk_ids)
479
@@ -485,36 +496,49 @@ class FusedMoEModularKernel(torch.nn.Module):
496
# reuse workspace13 for the output
497
fused_out = _resize_cache(workspace13, fused_out_shape)
498
488
- self.fused_experts.apply(fused_out,
489
- a1q,
490
- w1,
491
- w2,
492
- topk_ids=topk_ids,
493
- activation=activation,
494
- global_num_experts=global_num_experts,
495
- expert_map=expert_map,
496
- w1_scale=w1_scale,
497
- w2_scale=w2_scale,
498
- w1_zp=w1_zp,
499
- w2_zp=w2_zp,
500
- a1q_scale=a1q_scale,
501
- a2_scale=a2_scale,
502
- workspace13=workspace13,
503
- workspace2=workspace2,
504
- expert_tokens_meta=expert_tokens_meta)
499
+ self.fused_experts.apply(
500
+ fused_out,
501
+ a1q,
502
+ w1,
503
+ w2,
504
+ topk_weights=topk_weights,
505
+ topk_ids=topk_ids,
506
+ activation=activation,
507
+ global_num_experts=global_num_experts,
508
+ expert_map=expert_map,
509
+ w1_scale=w1_scale,
510
+ w2_scale=w2_scale,
511
+ w1_zp=w1_zp,
512
+ w2_zp=w2_zp,
513
+ a1q_scale=a1q_scale,
514
+ a2_scale=a2_scale,
515
+ workspace13=workspace13,
516
+ workspace2=workspace2,
517
+ expert_tokens_meta=expert_tokens_meta,
518
+ apply_router_weight_on_input=apply_router_weight_on_input)
519
520
return fused_out
521
522
def _maybe_chunk_fused_experts(
509
- self, a1: torch.Tensor, a1q: torch.Tensor, w1: torch.Tensor,
510
- w2: torch.Tensor, topk_ids: torch.Tensor, activation: str,
511
- global_num_experts: int, local_num_experts: int,
512
- expert_map: Optional[torch.Tensor],
513
- w1_scale: Optional[torch.Tensor], w2_scale: Optional[torch.Tensor],
514
- w1_zp: Optional[torch.Tensor], w2_zp: Optional[torch.Tensor],
515
- a1q_scale: Optional[torch.Tensor],
516
- a2_scale: Optional[torch.Tensor],
517
- expert_tokens_meta: Optional[ExpertTokensMetadata]
523
+ self,
524
+ a1: torch.Tensor,
525
+ a1q: torch.Tensor,
526
+ w1: torch.Tensor,
527
+ w2: torch.Tensor,
528
+ topk_weights: torch.Tensor,
529
+ topk_ids: torch.Tensor,
530
+ activation: str,
531
+ global_num_experts: int,
532
+ local_num_experts: int,
533
+ expert_map: Optional[torch.Tensor],
534
+ w1_scale: Optional[torch.Tensor],
535
+ w2_scale: Optional[torch.Tensor],
536
+ w1_zp: Optional[torch.Tensor],
537
+ w2_zp: Optional[torch.Tensor],
538
+ a1q_scale: Optional[torch.Tensor],
539
+ a2_scale: Optional[torch.Tensor],
540
+ expert_tokens_meta: Optional[ExpertTokensMetadata],
541
+ apply_router_weight_on_input: bool,
542
) -> torch.Tensor:
543
544
_, M, N, K, top_k = _moe_problem_size(a1q, w1, w2, topk_ids)
@@ -529,6 +553,7 @@ class FusedMoEModularKernel(torch.nn.Module):
553
a1q=a1q,
554
w1=w1,
555
w2=w2,
556
+ topk_weights=topk_weights,
557
topk_ids=topk_ids,
558
activation=activation,
559
global_num_experts=global_num_experts,
@@ -540,7 +565,8 @@ class FusedMoEModularKernel(torch.nn.Module):
565
w2_zp=w2_zp,
566
a1q_scale=a1q_scale,
567
a2_scale=a2_scale,
543
- expert_tokens_meta=expert_tokens_meta)
568
+ expert_tokens_meta=expert_tokens_meta,
569
+ apply_router_weight_on_input=apply_router_weight_on_input)
570
571
# Chunking required case
572
assert num_chunks > 1
@@ -557,11 +583,12 @@ class FusedMoEModularKernel(torch.nn.Module):
583
def slice_input_tensors(
584
chunk_idx: int
585
) -> tuple[torch.Tensor, Optional[torch.Tensor],
560
- Optional[torch.Tensor], torch.Tensor]:
586
+ Optional[torch.Tensor], torch.Tensor, torch.Tensor]:
587
s = chunk_idx * CHUNK_SIZE
588
e = min(s + CHUNK_SIZE, M)
589
return (a1q[s:e], _chunk_scales(a1q_scale, s, e),
564
- _chunk_scales(a2_scale, s, e), topk_ids[s:e])
590
+ _chunk_scales(a2_scale, s,
591
+ e), topk_ids[s:e], topk_weights[s:e])
592
593
def slice_output_tensor(chunk_idx: int) -> torch.Tensor:
594
assert fused_out.size(0) % M == 0, (
@@ -594,7 +621,7 @@ class FusedMoEModularKernel(torch.nn.Module):
621
expert_num_tokens_cpu=c_expert_num_tokens_cpu)
622
623
for chunk_idx in range(num_chunks):
597
- c_a1q, c_a1q_scale, c_a2_scale, c_topk_ids = (
624
+ c_a1q, c_a1q_scale, c_a2_scale, c_topk_ids, c_topk_weights = (
625
slice_input_tensors(chunk_idx))
626
627
c_expert_tokens_meta = None
@@ -603,23 +630,26 @@ class FusedMoEModularKernel(torch.nn.Module):
630
expert_tokens_meta, c_topk_ids, local_num_experts,
631
expert_map)
632
606
- self._do_fused_experts(fused_out=slice_output_tensor(chunk_idx),
607
- a1=a1,
608
- a1q=c_a1q,
609
- w1=w1,
610
- w2=w2,
611
- topk_ids=c_topk_ids,
612
- activation=activation,
613
- global_num_experts=global_num_experts,
614
- local_num_experts=local_num_experts,
615
- expert_map=expert_map,
616
- w1_scale=w1_scale,
617
- w2_scale=w2_scale,
618
- w1_zp=w1_zp,
619
- w2_zp=w2_zp,
620
- a1q_scale=c_a1q_scale,
621
- a2_scale=c_a2_scale,
622
- expert_tokens_meta=c_expert_tokens_meta)
633
+ self._do_fused_experts(
634
+ fused_out=slice_output_tensor(chunk_idx),
635
+ a1=a1,
636
+ a1q=c_a1q,
637
+ w1=w1,
638
+ w2=w2,
639
+ topk_weights=c_topk_weights,
640
+ topk_ids=c_topk_ids,
641
+ activation=activation,
642
+ global_num_experts=global_num_experts,
643
+ local_num_experts=local_num_experts,
644
+ expert_map=expert_map,
645
+ w1_scale=w1_scale,
646
+ w2_scale=w2_scale,
647
+ w1_zp=w1_zp,
648
+ w2_zp=w2_zp,
649
+ a1q_scale=c_a1q_scale,
650
+ a2_scale=c_a2_scale,
651
+ expert_tokens_meta=c_expert_tokens_meta,
652
+ apply_router_weight_on_input=apply_router_weight_on_input)
653
654
return fused_out
655
@@ -719,6 +749,7 @@ class FusedMoEModularKernel(torch.nn.Module):
749
a1q=a1q,
750
w1=w1,
751
w2=w2,
752
+ topk_weights=topk_weights,
753
topk_ids=topk_ids,
754
activation=activation,
755
global_num_experts=global_num_experts,
@@ -730,7 +761,8 @@ class FusedMoEModularKernel(torch.nn.Module):
761
w2_zp=w2_zp,
762
a1q_scale=a1q_scale,
763
a2_scale=a2_scale,
733
- expert_tokens_meta=expert_tokens_meta)
764
+ expert_tokens_meta=expert_tokens_meta,
765
+ apply_router_weight_on_input=apply_router_weight_on_input)
766
767
self.prepare_finalize.finalize(
768
output, fused_out, topk_weights, topk_ids,
vllm/model_executor/layers/fused_moe/topk_weight_and_reduce.py
+12
-5
@@ -48,11 +48,18 @@ class TopKWeightAndReduceNoOP(mk.TopKWeightAndReduce):
48
fused_expert_output: torch.Tensor, topk_weights: torch.Tensor,
49
topk_ids: torch.Tensor,
50
apply_router_weight_on_input: bool) -> torch.Tensor:
51
- # Relax this if an explicit copy is necessary. Note that,
52
- # if a copy is employed we have to make sure that the
53
- # tensors don't overlap
54
- assert output is None
55
- return fused_expert_output
51
+ # Weight application and reduction operations are already done.
52
+ if output is None:
53
+ return fused_expert_output
54
+
55
+ # MoEPrepareAndFinalizeNoEP needs the output to be in the `output`
56
+ # tensor.
57
+ assert output.size() == fused_expert_output.size(), (
58
+ "output shape is expected to match the fused_expert_output shape. "
59
+ f"But got output={output.size()}, "
60
+ f"used_expert_output={fused_expert_output.size()}")
61
+ output.copy_(fused_expert_output, non_blocking=True)
62
+ return output
63
64
65
class TopKWeightAndReduceContiguous(mk.TopKWeightAndReduce):
vllm/model_executor/layers/fused_moe/triton_deep_gemm_moe.py
+4
@@ -122,6 +122,7 @@ class TritonOrDeepGemmExperts(mk.FusedMoEPermuteExpertsUnpermute):
122
hidden_states: torch.Tensor,
123
w1: torch.Tensor,
124
w2: torch.Tensor,
125
+ topk_weights: torch.Tensor,
126
topk_ids: torch.Tensor,
127
activation: str,
128
global_num_experts: int,
@@ -135,6 +136,7 @@ class TritonOrDeepGemmExperts(mk.FusedMoEPermuteExpertsUnpermute):
136
workspace13: torch.Tensor,
137
workspace2: torch.Tensor,
138
expert_tokens_meta: Optional[mk.ExpertTokensMetadata],
139
+ apply_router_weight_on_input: bool,
140
):
141
use_deep_gemm = (self.allow_deep_gemm
142
and (_valid_deep_gemm(hidden_states, w1, w2)
@@ -148,6 +150,7 @@ class TritonOrDeepGemmExperts(mk.FusedMoEPermuteExpertsUnpermute):
150
hidden_states,
151
w1,
152
w2,
153
+ topk_weights,
154
topk_ids,
155
activation,
156
global_num_experts,
@@ -161,4 +164,5 @@ class TritonOrDeepGemmExperts(mk.FusedMoEPermuteExpertsUnpermute):
164
workspace13,
165
workspace2,
166
expert_tokens_meta,
167
+ apply_router_weight_on_input,
168
)