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, 11:00 UTC
[FEAT] [ROCm]: Add AITER CK 2 Stages MoE support (#17110)
Signed-off-by: tjtanaa <tunjian.tan@embeddedllm.com> Co-authored-by: Gregory Shtrasberg <Gregory.Shtrasberg@amd.com>
TJian committed
May 14, 2025 at 18:03 UTC
612c2edb4f940b26550ca64576995957e4118a12
7 files changed
+201
-112
tests/kernels/moe/test_moe.py
+7
@@ -224,9 +224,16 @@ def test_mixtral_moe(dtype: torch.dtype, padding: bool, use_rocm_aiter: bool,
224
"""Make sure our Mixtral MoE implementation agrees with the one from
225
huggingface."""
226
227
+ # clear the cache before every test
228
+ from vllm.model_executor.layers.fused_moe.rocm_aiter_fused_moe import (
229
+ is_rocm_aiter_moe_enabled)
230
+ is_rocm_aiter_moe_enabled.cache_clear()
231
if use_rocm_aiter:
232
monkeypatch.setenv("VLLM_ROCM_USE_AITER", "1")
233
234
+ if dtype == torch.float32:
235
+ pytest.skip("AITER ROCm test skip for float32")
236
+
237
# Instantiate our and huggingface's MoE blocks
238
config = MixtralConfig()
239
hf_moe = MixtralSparseMoeBlock(config).to(dtype).to("cuda")
tests/model_executor/test_enabled_custom_ops.py
+2
-22
@@ -8,10 +8,8 @@ from vllm.model_executor.custom_op import CustomOp
8
from vllm.model_executor.layers.activation import (GeluAndMul,
9
ReLUSquaredActivation,
10
SiluAndMul)
11
-from vllm.model_executor.layers.fused_moe.fused_moe import (
12
- dispatch_fused_experts_func, dispatch_topk_func,
13
- torch_vllm_inplace_fused_experts, torch_vllm_outplace_fused_experts,
14
- vllm_topk_softmax)
11
+from vllm.model_executor.layers.fused_moe.fused_moe import (dispatch_topk_func,
12
+ vllm_topk_softmax)
13
from vllm.model_executor.layers.fused_moe.rocm_aiter_fused_moe import (
14
is_rocm_aiter_moe_enabled)
15
from vllm.model_executor.layers.layernorm import (
@@ -142,24 +140,6 @@ def test_topk_dispatch(use_rocm_aiter: str, monkeypatch):
140
assert topk_func == vllm_topk_softmax
141
142
145
-@pytest.mark.parametrize("use_rocm_aiter", ["0", "1"])
146
-@pytest.mark.parametrize("inplace", [True, False])
147
-def test_fused_experts_dispatch(use_rocm_aiter: str, inplace: bool,
148
- monkeypatch):
149
-
150
- monkeypatch.setenv("VLLM_ROCM_USE_AITER", use_rocm_aiter)
151
- is_rocm_aiter_moe_enabled.cache_clear()
152
- fused_experts_func = dispatch_fused_experts_func(inplace)
153
- if current_platform.is_rocm() and int(use_rocm_aiter):
154
- from vllm.model_executor.layers.fused_moe.rocm_aiter_fused_moe import (
155
- rocm_aiter_fused_experts)
156
- assert fused_experts_func == rocm_aiter_fused_experts
157
- elif inplace:
158
- assert fused_experts_func == torch_vllm_inplace_fused_experts
159
- else:
160
- assert fused_experts_func == torch_vllm_outplace_fused_experts
161
-
162
-
143
@pytest.mark.parametrize("add_residual", [True, False])
144
@pytest.mark.parametrize("use_rocm_aiter", ["0", "1"])
145
@pytest.mark.parametrize("use_rocm_aiter_norm", ["0", "1"])
vllm/model_executor/layers/fused_moe/fused_moe.py
-3
@@ -1100,9 +1100,6 @@ def torch_vllm_outplace_fused_experts(**kwargs) -> torch.Tensor:
1100
1101
1102
def dispatch_fused_experts_func(inplace: bool) -> Callable[..., torch.Tensor]:
1103
- if is_rocm_aiter_moe_enabled():
1104
- from .rocm_aiter_fused_moe import rocm_aiter_fused_experts
1105
- return rocm_aiter_fused_experts
1103
if inplace:
1104
return torch_vllm_inplace_fused_experts
1105
return torch_vllm_outplace_fused_experts
vllm/model_executor/layers/fused_moe/layer.py
+27
-5
@@ -84,6 +84,16 @@ class FusedMoEMethodBase(QuantizeMethodBase):
84
class UnquantizedFusedMoEMethod(FusedMoEMethodBase, CustomOp):
85
"""MoE method without quantization."""
86
87
+ def __init__(self):
88
+ super().__init__()
89
+
90
+ self.rocm_aiter_moe_enabled = is_rocm_aiter_moe_enabled()
91
+ if self.rocm_aiter_moe_enabled:
92
+ from .rocm_aiter_fused_moe import rocm_aiter_fused_experts
93
+ self.rocm_aiter_fused_experts = rocm_aiter_fused_experts
94
+ else:
95
+ self.rocm_aiter_fused_experts = None # type: ignore
96
+
97
def create_weights(self, layer: torch.nn.Module, num_experts: int,
98
hidden_size: int, intermediate_size_per_partition: int,
99
params_dtype: torch.dtype, **extra_weight_attrs):
@@ -126,11 +136,13 @@ class UnquantizedFusedMoEMethod(FusedMoEMethodBase, CustomOp):
136
layer.w2_weight.data = self._maybe_pad_weight(layer.w2_weight.data)
137
# Lazy import to avoid importing triton.
138
from vllm.model_executor.layers.fused_moe.rocm_aiter_fused_moe import (
129
- is_rocm_aiter_moe_enabled, shuffle_weights)
130
- if is_rocm_aiter_moe_enabled():
131
- # reshaping weights is required for aiter moe kernel.
132
- shuffled_w13, shuffled_w2 = shuffle_weights(
133
- layer.w13_weight.data, layer.w2_weight.data)
139
+ shuffle_weights)
140
+
141
+ if self.rocm_aiter_moe_enabled:
142
+ # use 2stage ck moe layout
143
+ shuffled_w13, shuffled_w2 = shuffle_weights(layer.w13_weight.data,
144
+ layer.w2_weight.data,
145
+ layout=(32, 32))
146
147
layer.w13_weight.data = shuffled_w13
148
layer.w2_weight.data = shuffled_w2
@@ -211,6 +223,16 @@ class UnquantizedFusedMoEMethod(FusedMoEMethodBase, CustomOp):
223
scoring_func=scoring_func,
224
e_score_correction_bias=e_score_correction_bias)
225
226
+ if self.rocm_aiter_moe_enabled:
227
+ return self.rocm_aiter_fused_experts(
228
+ hidden_states=x,
229
+ w1=layer.w13_weight,
230
+ w2=layer.w2_weight,
231
+ topk_weights=topk_weights,
232
+ topk_ids=topk_ids,
233
+ activation=activation,
234
+ apply_router_weight_on_input=apply_router_weight_on_input)
235
+
236
return fused_experts(
237
hidden_states=x,
238
w1=layer.w13_weight,
vllm/model_executor/layers/fused_moe/rocm_aiter_fused_moe.py
+106
-67
@@ -20,7 +20,7 @@ def rocm_aiter_asm_moe_tkw1_impl(
20
hidden_states: torch.Tensor,
21
w1: torch.Tensor,
22
w2: torch.Tensor,
23
- topk_weight: torch.Tensor,
23
+ topk_weights: torch.Tensor,
24
topk_ids: torch.Tensor,
25
fc1_scale: Optional[torch.Tensor] = None,
26
fc2_scale: Optional[torch.Tensor] = None,
@@ -40,7 +40,7 @@ def rocm_aiter_asm_moe_tkw1_impl(
40
return asm_moe_tkw1(hidden_states,
41
w1,
42
w2,
43
- topk_weight,
43
+ topk_weights,
44
topk_ids,
45
fc1_scale=fc1_scale,
46
fc2_scale=fc2_scale,
@@ -56,7 +56,7 @@ def rocm_aiter_asm_moe_tkw1_fake(
56
hidden_states: torch.Tensor,
57
w1: torch.Tensor,
58
w2: torch.Tensor,
59
- topk_weight: torch.Tensor,
59
+ topk_weights: torch.Tensor,
60
topk_ids: torch.Tensor,
61
fc1_scale: Optional[torch.Tensor] = None,
62
fc2_scale: Optional[torch.Tensor] = None,
@@ -69,23 +69,6 @@ def rocm_aiter_asm_moe_tkw1_fake(
69
return torch.empty_like(hidden_states)
70
71
72
-def rocm_aiter_ck_moe_impl(hidden_states: torch.Tensor, w1: torch.Tensor,
73
- w2: torch.Tensor, topk_weights: torch.Tensor,
74
- topk_ids: torch.Tensor) -> torch.Tensor:
75
- from aiter import ck_moe
76
- return ck_moe(hidden_states=hidden_states,
77
- w1=w1,
78
- w2=w2,
79
- topk_weights=topk_weights,
80
- topk_ids=topk_ids)
81
-
82
-
83
-def rocm_aiter_ck_moe_fake(hidden_states: torch.Tensor, w1: torch.Tensor,
84
- w2: torch.Tensor, topk_weights: torch.Tensor,
85
- topk_ids: torch.Tensor) -> torch.Tensor:
86
- return torch.empty_like(hidden_states)
87
-
88
-
72
def rocm_aiter_fmoe_fp8_blockscale_g1u1_impl(
73
topk_ids: torch.Tensor,
74
topk_weights: torch.Tensor,
@@ -152,7 +135,7 @@ def rocm_aiter_fmoe_fp8_blockscale_g1u1_fake(
135
def rocm_aiter_asm_moe_impl(hidden_states: torch.Tensor,
136
w1: torch.Tensor,
137
w2: torch.Tensor,
155
- topk_weight: torch.Tensor,
138
+ topk_weights: torch.Tensor,
139
topk_ids: torch.Tensor,
140
fc1_scale: Optional[torch.Tensor] = None,
141
fc2_scale: Optional[torch.Tensor] = None,
@@ -175,7 +158,7 @@ def rocm_aiter_asm_moe_impl(hidden_states: torch.Tensor,
158
return rocm_aiter_asm_fmoe.asm_moe(hidden_states=hidden_states,
159
w1=w1,
160
w2=w2,
178
- topk_weight=topk_weight,
161
+ topk_weight=topk_weights,
162
topk_ids=topk_ids,
163
fc1_scale=fc1_scale,
164
fc2_scale=fc2_scale,
@@ -188,7 +171,7 @@ def rocm_aiter_asm_moe_impl(hidden_states: torch.Tensor,
171
def rocm_aiter_asm_moe_fake(hidden_states: torch.Tensor,
172
w1: torch.Tensor,
173
w2: torch.Tensor,
191
- topk_weight: torch.Tensor,
174
+ topk_weights: torch.Tensor,
175
topk_ids: torch.Tensor,
176
fc1_scale: Optional[torch.Tensor] = None,
177
fc2_scale: Optional[torch.Tensor] = None,
@@ -199,6 +182,49 @@ def rocm_aiter_asm_moe_fake(hidden_states: torch.Tensor,
182
return torch.empty_like(hidden_states)
183
184
185
+def rocm_aiter_ck_moe_2stages_impl(
186
+ hidden_states: torch.Tensor,
187
+ w1: torch.Tensor,
188
+ w2: torch.Tensor,
189
+ topk_weights: torch.Tensor,
190
+ topk_ids: torch.Tensor,
191
+ fc1_scale: Optional[torch.Tensor] = None,
192
+ fc2_scale: Optional[torch.Tensor] = None,
193
+ a1_scale: Optional[torch.Tensor] = None,
194
+ a2_scale: Optional[torch.Tensor] = None,
195
+ block_size: Optional[list[int]] = None,
196
+ expert_mask: Optional[torch.Tensor] = None,
197
+) -> torch.Tensor:
198
+ from aiter.fused_moe_bf16_asm import ck_moe_2stages
199
+ return ck_moe_2stages(a1=hidden_states,
200
+ w1=w1,
201
+ w2=w2,
202
+ topk_weight=topk_weights,
203
+ topk_ids=topk_ids,
204
+ fc1_scale=fc1_scale,
205
+ fc2_scale=fc2_scale,
206
+ a1_scale=a1_scale,
207
+ a2_scale=a2_scale,
208
+ block_size=block_size,
209
+ expert_mask=expert_mask)
210
+
211
+
212
+def rocm_aiter_ck_moe_2stages_fake(
213
+ hidden_states: torch.Tensor,
214
+ w1: torch.Tensor,
215
+ w2: torch.Tensor,
216
+ topk_weights: torch.Tensor,
217
+ topk_ids: torch.Tensor,
218
+ fc1_scale: Optional[torch.Tensor] = None,
219
+ fc2_scale: Optional[torch.Tensor] = None,
220
+ a1_scale: Optional[torch.Tensor] = None,
221
+ a2_scale: Optional[torch.Tensor] = None,
222
+ block_size: Optional[list[int]] = None,
223
+ expert_mask: Optional[torch.Tensor] = None,
224
+) -> torch.Tensor:
225
+ return torch.empty_like(hidden_states)
226
+
227
+
228
def rocm_aiter_topk_softmax_impl(topk_weights: torch.Tensor,
229
topk_indices: torch.Tensor,
230
token_expert_indices: torch.Tensor,
@@ -258,14 +284,6 @@ if current_platform.is_rocm():
284
dispatch_key=current_platform.dispatch_key,
285
)
286
261
- direct_register_custom_op(
262
- op_name="rocm_aiter_ck_moe",
263
- op_func=rocm_aiter_ck_moe_impl,
264
- mutates_args=[],
265
- fake_impl=rocm_aiter_ck_moe_fake,
266
- dispatch_key=current_platform.dispatch_key,
267
- )
268
-
287
direct_register_custom_op(
288
op_name="rocm_aiter_fmoe_fp8_blockscale_g1u1",
289
op_func=rocm_aiter_fmoe_fp8_blockscale_g1u1_impl,
@@ -282,6 +300,14 @@ if current_platform.is_rocm():
300
dispatch_key=current_platform.dispatch_key,
301
)
302
303
+ direct_register_custom_op(
304
+ op_name="rocm_aiter_ck_moe_2stages",
305
+ op_func=rocm_aiter_ck_moe_2stages_impl,
306
+ mutates_args=[],
307
+ fake_impl=rocm_aiter_ck_moe_2stages_fake,
308
+ dispatch_key=current_platform.dispatch_key,
309
+ )
310
+
311
direct_register_custom_op(
312
op_name="rocm_aiter_topk_softmax",
313
op_func=rocm_aiter_topk_softmax_impl,
@@ -331,29 +357,21 @@ def rocm_aiter_biased_group_topk(
357
return topk_weights, topk_ids
358
359
334
-def rocm_aiter_fused_experts(hidden_states: torch.Tensor,
335
- w1: torch.Tensor,
336
- w2: torch.Tensor,
337
- topk_weights: torch.Tensor,
338
- topk_ids: torch.Tensor,
339
- inplace: bool = False,
340
- activation: str = "silu",
341
- apply_router_weight_on_input: bool = False,
342
- use_fp8_w8a8: bool = False,
343
- use_int8_w8a8: bool = False,
344
- use_int8_w8a16: bool = False,
345
- use_int4_w4a16: bool = False,
346
- per_channel_quant: bool = False,
347
- global_num_experts: int = -1,
348
- expert_map: Optional[torch.Tensor] = None,
349
- w1_scale: Optional[torch.Tensor] = None,
350
- w2_scale: Optional[torch.Tensor] = None,
351
- w1_zp: Optional[torch.Tensor] = None,
352
- w2_zp: Optional[torch.Tensor] = None,
353
- a1_scale: Optional[torch.Tensor] = None,
354
- a2_scale: Optional[torch.Tensor] = None,
355
- block_shape: Optional[list[int]] = None,
356
- allow_deep_gemm: bool = False) -> torch.Tensor:
360
+def rocm_aiter_fused_experts(
361
+ hidden_states: torch.Tensor,
362
+ w1: torch.Tensor,
363
+ w2: torch.Tensor,
364
+ topk_weights: torch.Tensor,
365
+ topk_ids: torch.Tensor,
366
+ activation: str = "silu",
367
+ apply_router_weight_on_input: bool = False,
368
+ use_fp8_w8a8: bool = False,
369
+ per_channel_quant: bool = False,
370
+ w1_scale: Optional[torch.Tensor] = None,
371
+ w2_scale: Optional[torch.Tensor] = None,
372
+ a1_scale: Optional[torch.Tensor] = None,
373
+ a2_scale: Optional[torch.Tensor] = None,
374
+ block_shape: Optional[list[int]] = None) -> torch.Tensor:
375
376
from vllm.model_executor.layers.quantization.utils.fp8_utils import (
377
per_token_group_quant_fp8)
@@ -376,8 +394,8 @@ def rocm_aiter_fused_experts(hidden_states: torch.Tensor,
394
a1, a1_scale = per_token_group_quant_fp8(hidden_states, block_shape[1])
395
396
return torch.ops.vllm.rocm_aiter_fmoe_fp8_blockscale_g1u1(
379
- topk_ids, topk_weights, hidden_states.dtype, expert_map, a1, w1,
380
- w2, w1_scale, w2_scale, a1_scale, block_shape, None)
397
+ topk_ids, topk_weights, hidden_states.dtype, None, a1, w1, w2,
398
+ w1_scale, w2_scale, a1_scale, block_shape, None)
399
400
# w8a8 per-channel quantization
401
elif per_channel_quant and apply_router_weight_on_input and use_fp8_w8a8:
@@ -402,17 +420,36 @@ def rocm_aiter_fused_experts(hidden_states: torch.Tensor,
420
fc2_smooth_scale=None,
421
a16=False,
422
per_tensor_quant_scale=None,
405
- expert_mask=expert_map,
423
+ expert_mask=None,
424
activation_str=activation)
425
426
# w8a8 per-tensor activation per-tensor weight
427
elif use_fp8_w8a8:
428
assert not apply_router_weight_on_input, (
429
"apply_router_weight_on_input is not supported for fp8_w8a8")
430
+
431
+ # - faster static per-tensor-activation static per-tensor-weight
432
+ # fp8 quantization w8a8
433
+ if a1_scale is not None and a2_scale is not None:
434
+ return torch.ops.vllm.rocm_aiter_ck_moe_2stages(
435
+ hidden_states=hidden_states,
436
+ w1=w1,
437
+ w2=w2,
438
+ topk_weights=topk_weights,
439
+ topk_ids=topk_ids,
440
+ fc1_scale=w1_scale,
441
+ fc2_scale=w2_scale,
442
+ a1_scale=a1_scale,
443
+ a2_scale=a2_scale)
444
+
445
+ # - fallback static per-tensor-activation static per-tensor-weight
446
+ # fp8 quantization w8a8
447
+ # - dynamic per-tensor activation static per-tensor-weight
448
+ # fp8 quantization w8a8
449
return torch.ops.vllm.rocm_aiter_asm_moe(hidden_states=hidden_states,
450
w1=w1,
451
w2=w2,
415
- topk_weight=topk_weights,
452
+ topk_weights=topk_weights,
453
topk_ids=topk_ids,
454
fc1_scale=w1_scale,
455
fc2_scale=w2_scale,
@@ -432,12 +469,12 @@ def rocm_aiter_fused_experts(hidden_states: torch.Tensor,
469
topk_ids = topk_ids.to(torch.int32)
470
topk_weights = torch.ones_like(topk_weights, dtype=torch.float32)
471
435
- # w16a16 fallback to rocm_aiter_ck_moe w16a16
436
- return torch.ops.vllm.rocm_aiter_ck_moe(hidden_states=hidden_states,
437
- w1=w1,
438
- w2=w2,
439
- topk_weights=topk_weights,
440
- topk_ids=topk_ids)
472
+ return torch.ops.vllm.rocm_aiter_ck_moe_2stages(
473
+ hidden_states=hidden_states,
474
+ w1=w1,
475
+ w2=w2,
476
+ topk_weights=topk_weights,
477
+ topk_ids=topk_ids)
478
479
480
def rocm_aiter_topk_softmax(topk_weights: torch.Tensor,
@@ -451,7 +488,8 @@ def rocm_aiter_topk_softmax(topk_weights: torch.Tensor,
488
return topk_weights, topk_indices
489
490
454
-def shuffle_weights(*tensors: torch.Tensor) -> tuple[torch.Tensor, ...]:
491
+def shuffle_weights(*tensors: torch.Tensor,
492
+ layout: tuple[int, int]) -> tuple[torch.Tensor, ...]:
493
"""
494
Applies shuffle_weight function from AITER to each
495
input tensor and returns them.
@@ -463,7 +501,8 @@ def shuffle_weights(*tensors: torch.Tensor) -> tuple[torch.Tensor, ...]:
501
A Tuple of shuffled tensors.
502
"""
503
from aiter.ops.shuffle import shuffle_weight
466
- return tuple(shuffle_weight(tensor) for tensor in tensors)
504
+
505
+ return tuple(shuffle_weight(tensor, layout=layout) for tensor in tensors)
506
507
508
def expand_weights(*tensors: torch.Tensor,
@@ -485,4 +524,4 @@ def expand_weights(*tensors: torch.Tensor,
524
525
return tuple(
526
tensor.unsqueeze(-1).unsqueeze(-1).expand((-1, dim, -1))
488
- for tensor, dim in zip(tensors, expansion_dims))
527
+ for tensor, dim in zip(tensors, expansion_dims))
\ No newline at end of file
vllm/model_executor/layers/quantization/compressed_tensors/compressed_tensors_moe.py
+25
-7
@@ -125,6 +125,10 @@ class CompressedTensorsW8A8Fp8MoEMethod(CompressedTensorsMoEMethod):
125
# Disable marlin for rocm
126
if current_platform.is_rocm():
127
self.use_marlin = False
128
+ from vllm.model_executor.layers.fused_moe.rocm_aiter_fused_moe import (
129
+ is_rocm_aiter_moe_enabled)
130
+
131
+ self.rocm_aiter_moe_enabled = is_rocm_aiter_moe_enabled()
132
133
def create_weights(self, layer: torch.nn.Module, num_experts: int,
134
hidden_size: int, intermediate_size_per_partition: int,
@@ -276,24 +280,22 @@ class CompressedTensorsW8A8Fp8MoEMethod(CompressedTensorsMoEMethod):
280
layer.w13_weight_scale = torch.nn.Parameter(max_w13_scales,
281
requires_grad=False)
282
279
- from vllm.model_executor.layers.fused_moe.rocm_aiter_fused_moe import (
280
- is_rocm_aiter_moe_enabled)
281
-
283
# Property to determine if AITER is used
283
- if is_rocm_aiter_moe_enabled():
284
+ if self.rocm_aiter_moe_enabled:
285
from vllm.model_executor.layers.fused_moe.rocm_aiter_fused_moe import ( # noqa E501
286
rocm_aiter_fused_experts, shuffle_weights)
287
288
# reshaping weights is required for aiter moe kernel.
288
- shuffled_w13, shuffled_w2 = shuffle_weights(
289
- layer.w13_weight.data, layer.w2_weight.data)
289
+ shuffled_w13, shuffled_w2 = shuffle_weights(layer.w13_weight.data,
290
+ layer.w2_weight.data,
291
+ layout=(16, 16))
292
293
layer.w13_weight = torch.nn.Parameter(shuffled_w13,
294
requires_grad=False)
295
layer.w2_weight = torch.nn.Parameter(shuffled_w2,
296
requires_grad=False)
297
296
- self.fused_experts_func = rocm_aiter_fused_experts
298
+ self.rocm_aiter_fused_experts_func = rocm_aiter_fused_experts
299
else:
300
from vllm.model_executor.layers.fused_moe import fused_experts
301
self.fused_experts_func = fused_experts
@@ -335,6 +337,22 @@ class CompressedTensorsW8A8Fp8MoEMethod(CompressedTensorsMoEMethod):
337
scoring_func=scoring_func,
338
e_score_correction_bias=e_score_correction_bias)
339
340
+ if self.rocm_aiter_moe_enabled:
341
+ return self.rocm_aiter_fused_experts_func(
342
+ hidden_states=x,
343
+ w1=layer.w13_weight,
344
+ w2=layer.w2_weight,
345
+ topk_weights=topk_weights,
346
+ topk_ids=topk_ids,
347
+ activation=activation,
348
+ apply_router_weight_on_input=apply_router_weight_on_input,
349
+ use_fp8_w8a8=True,
350
+ per_channel_quant=self.weight_quant.strategy ==
351
+ QuantizationStrategy.CHANNEL,
352
+ w1_scale=layer.w13_weight_scale,
353
+ w2_scale=layer.w2_weight_scale,
354
+ a1_scale=layer.w13_input_scale,
355
+ a2_scale=layer.w2_input_scale)
356
if self.use_marlin:
357
assert activation == "silu", (
358
f"{activation} not supported for Marlin MoE.")
vllm/model_executor/layers/quantization/fp8.py
+34
-8
@@ -591,6 +591,8 @@ class Fp8MoEMethod(FusedMoEMethodBase):
591
from vllm.model_executor.layers.fused_moe.rocm_aiter_fused_moe import (
592
expand_weights, is_rocm_aiter_moe_enabled, shuffle_weights)
593
594
+ self.rocm_aiter_moe_enabled = is_rocm_aiter_moe_enabled()
595
+
596
# TODO (rob): refactor block quant into separate class.
597
if self.block_quant:
598
assert self.quant_config.activation_scheme == "dynamic"
@@ -616,10 +618,12 @@ class Fp8MoEMethod(FusedMoEMethodBase):
618
layer.w2_weight = Parameter(w2_weight, requires_grad=False)
619
layer.w2_weight_scale_inv = Parameter(w2_weight_scale_inv,
620
requires_grad=False)
619
- if is_rocm_aiter_moe_enabled():
621
+ if self.rocm_aiter_moe_enabled:
622
# reshaping weights is required for aiter moe kernel.
623
shuffled_w13, shuffled_w2 = shuffle_weights(
622
- layer.w13_weight.data, layer.w2_weight.data)
624
+ layer.w13_weight.data,
625
+ layer.w2_weight.data,
626
+ layout=(16, 16))
627
628
layer.w13_weight = torch.nn.Parameter(shuffled_w13,
629
requires_grad=False)
@@ -663,7 +667,7 @@ class Fp8MoEMethod(FusedMoEMethodBase):
667
requires_grad=False)
668
layer.w2_weight = torch.nn.Parameter(w2_weight,
669
requires_grad=False)
666
- if is_rocm_aiter_moe_enabled():
670
+ if self.rocm_aiter_moe_enabled:
671
# reshaping weights is required for aiter moe kernel.
672
w13_scales, w2_scales = expand_weights(
673
layer.w13_weight_scale.data,
@@ -676,8 +680,9 @@ class Fp8MoEMethod(FusedMoEMethodBase):
680
layer.w2_weight_scale = torch.nn.Parameter(
681
w2_scales.contiguous(), requires_grad=False)
682
679
- shuffled_w13, shuffled_w2 = shuffle_weights(
680
- layer.w13_weight, layer.w2_weight)
683
+ shuffled_w13, shuffled_w2 = shuffle_weights(layer.w13_weight,
684
+ layer.w2_weight,
685
+ layout=(16, 16))
686
687
layer.w13_weight = torch.nn.Parameter(shuffled_w13,
688
requires_grad=False)
@@ -748,7 +753,7 @@ class Fp8MoEMethod(FusedMoEMethodBase):
753
dq_weight, max_w13_scales[expert_id])
754
start += shard_size
755
751
- if is_rocm_aiter_moe_enabled():
756
+ if self.rocm_aiter_moe_enabled:
757
# reshaping weights is required for aiter moe kernel.
758
expansion_dims = [
759
layer.w13_weight.shape[1], layer.w2_weight.shape[1]
@@ -760,8 +765,9 @@ class Fp8MoEMethod(FusedMoEMethodBase):
765
layer.w2_weight_scale = torch.nn.Parameter(
766
w2_scales.contiguous(), requires_grad=False)
767
763
- shuffled_w13, shuffled_w2 = shuffle_weights(
764
- layer.w13_weight, layer.w2_weight)
768
+ shuffled_w13, shuffled_w2 = shuffle_weights(layer.w13_weight,
769
+ layer.w2_weight,
770
+ layout=(32, 32))
771
772
layer.w13_weight = torch.nn.Parameter(shuffled_w13,
773
requires_grad=False)
@@ -796,6 +802,8 @@ class Fp8MoEMethod(FusedMoEMethodBase):
802
activation: str = "silu",
803
) -> torch.Tensor:
804
from vllm.model_executor.layers.fused_moe import fused_experts
805
+ from vllm.model_executor.layers.fused_moe.rocm_aiter_fused_moe import (
806
+ rocm_aiter_fused_experts)
807
808
topk_weights, topk_ids = FusedMoE.select_experts(
809
hidden_states=x,
@@ -810,6 +818,24 @@ class Fp8MoEMethod(FusedMoEMethodBase):
818
e_score_correction_bias=e_score_correction_bias,
819
)
820
821
+ if self.rocm_aiter_moe_enabled:
822
+ return rocm_aiter_fused_experts(
823
+ x,
824
+ layer.w13_weight,
825
+ layer.w2_weight,
826
+ topk_weights=topk_weights,
827
+ topk_ids=topk_ids,
828
+ activation=activation,
829
+ use_fp8_w8a8=True,
830
+ apply_router_weight_on_input=apply_router_weight_on_input,
831
+ w1_scale=(layer.w13_weight_scale_inv
832
+ if self.block_quant else layer.w13_weight_scale),
833
+ w2_scale=(layer.w2_weight_scale_inv
834
+ if self.block_quant else layer.w2_weight_scale),
835
+ a1_scale=layer.w13_input_scale,
836
+ a2_scale=layer.w2_input_scale,
837
+ block_shape=self.quant_config.weight_block_size)
838
+
839
if self.use_marlin:
840
assert activation == "silu", (
841
f"{activation} not supported for Marlin MoE.")