main
py 481 lines 13.7 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 from dataclasses import dataclass
4
5 import torch
6
7 # Fused experts and PrepareFinalize imports
8 import vllm.model_executor.layers.fused_moe.modular_kernel as mk
9 from vllm.model_executor.layers.fused_moe import TritonExperts
10 from vllm.model_executor.layers.fused_moe.config import (
11 FusedMoEConfig,
12 FusedMoEQuantConfig,
13 )
14 from vllm.model_executor.layers.fused_moe.experts.batched_deep_gemm_moe import (
15 BatchedDeepGemmExperts,
16 )
17 from vllm.model_executor.layers.fused_moe.experts.deep_gemm_moe import DeepGemmExperts
18 from vllm.model_executor.layers.fused_moe.experts.fused_batched_moe import (
19 BatchedTritonExperts,
20 NaiveBatchedExperts,
21 )
22 from vllm.model_executor.layers.fused_moe.experts.triton_deep_gemm_moe import (
23 TritonOrDeepGemmExperts,
24 )
25 from vllm.model_executor.layers.fused_moe.prepare_finalize import (
26 MoEPrepareAndFinalizeNoDPEPModular,
27 )
28 from vllm.model_executor.layers.quantization.utils.nvfp4_utils import (
29 cutlass_fp4_supported,
30 )
31 from vllm.model_executor.layers.quantization.utils.w8a8_utils import (
32 cutlass_fp8_supported,
33 )
34 from vllm.platforms import current_platform
35 from vllm.utils.deep_gemm import is_deep_gemm_supported
36 from vllm.utils.flashinfer import (
37 has_flashinfer_cutlass_fused_moe,
38 has_flashinfer_nvlink_one_sided,
39 has_flashinfer_trtllm_fused_moe,
40 )
41 from vllm.utils.import_utils import (
42 has_aiter,
43 has_deep_ep,
44 has_deep_ep_v2,
45 has_deep_gemm,
46 has_mori,
47 )
48
49
50 @dataclass
51 class TestMoEQuantConfig:
52 quant_dtype: torch.dtype | str | None
53 per_out_ch_quant: bool
54 per_act_token_quant: bool
55 block_shape: list[int] | None
56
57
58 @dataclass
59 class PrepareFinalizeInfo:
60 activation_format: mk.FusedMoEActivationFormat
61 supported_dtypes: list[torch.dtype | str]
62 blocked_quantization_support: bool
63 backend: str | None
64 supports_apply_weight_on_input: bool = True
65
66
67 @dataclass
68 class ExpertInfo:
69 activation_format: mk.FusedMoEActivationFormat
70 supported_dtypes: list[torch.dtype | str]
71 blocked_quantization_support: bool
72 needs_matching_quant: bool = False
73 needs_deep_gemm: bool = False
74 needs_aiter: bool = False
75
76
77 PREPARE_FINALIZE_INFO: dict[
78 mk.FusedMoEPrepareAndFinalizeModular, PrepareFinalizeInfo
79 ] = {}
80 EXPERT_INFO: dict[mk.FusedMoEExpertsModular, ExpertInfo] = {}
81 MK_ALL_PREPARE_FINALIZE_TYPES: list[mk.FusedMoEPrepareAndFinalizeModular] = []
82 MK_MULTI_GPU_PREPARE_FINALIZE_TYPES: list[mk.FusedMoEPrepareAndFinalizeModular] = []
83 MK_SINGLE_GPU_PREPARE_FINALIZE_TYPES: list[mk.FusedMoEPrepareAndFinalizeModular] = []
84 MK_FUSED_EXPERT_TYPES: list[mk.FusedMoEExpertsModular] = []
85
86 standard_format = mk.FusedMoEActivationFormat.Standard
87 batched_format = mk.FusedMoEActivationFormat.BatchedExperts
88 common_float_types: list[torch.dtype | str] = [
89 current_platform.fp8_dtype(),
90 torch.bfloat16,
91 torch.float16,
92 torch.float32,
93 ]
94 common_float_and_int_types = common_float_types + [torch.int8]
95 nvfp4_types = ["nvfp4"]
96 fp8_types = [current_platform.fp8_dtype()]
97
98
99 def register_prepare_and_finalize(
100 kind,
101 activation_format: mk.FusedMoEActivationFormat,
102 supported_dtypes: list[torch.dtype | str],
103 blocked_quantization_support: bool,
104 backend: str | None,
105 force_multigpu: bool = False,
106 supports_apply_weight_on_input: bool = True,
107 ):
108 global PREPARE_FINALIZE_INFO
109 global MK_ALL_PREPARE_FINALIZE_TYPES
110 global MK_MULTI_GPU_PREPARE_FINALIZE_TYPES
111 global MK_SINGLE_GPU_PREPARE_FINALIZE_TYPES
112 assert kind not in PREPARE_FINALIZE_INFO
113
114 PREPARE_FINALIZE_INFO[kind] = PrepareFinalizeInfo(
115 activation_format,
116 supported_dtypes,
117 blocked_quantization_support,
118 backend,
119 supports_apply_weight_on_input,
120 )
121 MK_ALL_PREPARE_FINALIZE_TYPES.append(kind)
122 if backend is not None or force_multigpu:
123 MK_MULTI_GPU_PREPARE_FINALIZE_TYPES.append(kind)
124 else:
125 MK_SINGLE_GPU_PREPARE_FINALIZE_TYPES.append(kind)
126
127
128 def register_experts(
129 kind,
130 activation_format: mk.FusedMoEActivationFormat,
131 supported_dtypes: list[torch.dtype | str],
132 blocked_quantization_support: bool,
133 needs_matching_quant: bool = False,
134 needs_deep_gemm: bool = False,
135 needs_aiter: bool = False,
136 ):
137 global EXPERT_INFO
138 global MK_FUSED_EXPERT_TYPES
139 assert kind not in EXPERT_INFO
140
141 EXPERT_INFO[kind] = ExpertInfo(
142 activation_format,
143 supported_dtypes,
144 blocked_quantization_support,
145 needs_matching_quant,
146 needs_deep_gemm,
147 needs_aiter,
148 )
149
150 MK_FUSED_EXPERT_TYPES.append(kind)
151
152
153 def prepare_finalize_info(kind) -> PrepareFinalizeInfo:
154 info = PREPARE_FINALIZE_INFO.get(kind)
155 assert info is not None
156 return info
157
158
159 def expert_info(kind) -> ExpertInfo:
160 info = EXPERT_INFO.get(kind)
161 assert info is not None
162 return info
163
164
165 register_prepare_and_finalize(
166 MoEPrepareAndFinalizeNoDPEPModular,
167 standard_format,
168 common_float_types,
169 blocked_quantization_support=True,
170 backend=None,
171 )
172
173 register_experts(
174 BatchedTritonExperts,
175 batched_format,
176 common_float_types,
177 blocked_quantization_support=True,
178 needs_matching_quant=True,
179 )
180
181 register_experts(
182 TritonExperts,
183 standard_format,
184 common_float_and_int_types,
185 blocked_quantization_support=True,
186 needs_matching_quant=True,
187 )
188
189 register_experts(
190 NaiveBatchedExperts,
191 batched_format,
192 common_float_and_int_types,
193 blocked_quantization_support=True,
194 )
195
196 # Disable on blackwell for now
197 if has_deep_ep() and not current_platform.has_device_capability(100):
198 from vllm.model_executor.layers.fused_moe.prepare_finalize.deepep_ht import (
199 DeepEPHTPrepareAndFinalize,
200 )
201 from vllm.model_executor.layers.fused_moe.prepare_finalize.deepep_ll import (
202 DeepEPLLPrepareAndFinalize,
203 )
204
205 register_prepare_and_finalize(
206 DeepEPHTPrepareAndFinalize,
207 standard_format,
208 common_float_types,
209 blocked_quantization_support=True,
210 backend="deepep_high_throughput",
211 )
212
213 register_prepare_and_finalize(
214 DeepEPLLPrepareAndFinalize,
215 batched_format,
216 common_float_types,
217 blocked_quantization_support=True,
218 backend="deepep_low_latency",
219 )
220
221 if has_deep_ep_v2() and current_platform.has_device_capability(100):
222 from vllm.model_executor.layers.fused_moe.prepare_finalize.deepep_v2 import (
223 DeepEPV2PrepareAndFinalize,
224 )
225
226 register_prepare_and_finalize(
227 DeepEPV2PrepareAndFinalize,
228 standard_format,
229 common_float_types,
230 blocked_quantization_support=True,
231 backend="deepep_v2",
232 )
233
234 if has_mori():
235 from vllm.model_executor.layers.fused_moe.prepare_finalize.mori import (
236 MoriPrepareAndFinalize,
237 )
238
239 register_prepare_and_finalize(
240 MoriPrepareAndFinalize,
241 standard_format,
242 fp8_types,
243 blocked_quantization_support=True,
244 backend="mori_high_throughput",
245 supports_apply_weight_on_input=False,
246 )
247
248 if has_flashinfer_cutlass_fused_moe() and current_platform.has_device_capability(100):
249 from vllm.model_executor.layers.fused_moe.experts.flashinfer_cutlass_moe import (
250 FlashInferExperts,
251 )
252 from vllm.model_executor.layers.fused_moe.prepare_finalize.flashinfer_nvlink_two_sided import ( # noqa: E501
253 FlashInferNVLinkTwoSidedPrepareAndFinalize,
254 )
255
256 register_prepare_and_finalize(
257 FlashInferNVLinkTwoSidedPrepareAndFinalize,
258 standard_format,
259 nvfp4_types + fp8_types,
260 blocked_quantization_support=True,
261 backend=None,
262 force_multigpu=True,
263 supports_apply_weight_on_input=False,
264 )
265
266 register_experts(
267 FlashInferExperts,
268 standard_format,
269 nvfp4_types + fp8_types,
270 blocked_quantization_support=True,
271 # Note: this is a hack to get it to run for now
272 )
273 else:
274 FlashInferCutlassMoEPrepareAndFinalize = None
275 FlashInferExperts = None
276
277 if (
278 has_flashinfer_nvlink_one_sided()
279 and has_flashinfer_cutlass_fused_moe()
280 and current_platform.has_device_capability(100)
281 ):
282 from vllm.model_executor.layers.fused_moe.prepare_finalize.flashinfer_nvlink_one_sided import ( # noqa: E501
283 FlashInferNVLinkOneSidedPrepareAndFinalize,
284 )
285
286 register_prepare_and_finalize(
287 FlashInferNVLinkOneSidedPrepareAndFinalize,
288 standard_format,
289 nvfp4_types,
290 blocked_quantization_support=False,
291 backend="flashinfer_nvlink_one_sided",
292 supports_apply_weight_on_input=False,
293 )
294
295 if has_flashinfer_cutlass_fused_moe() and current_platform.has_device_capability(100):
296 from vllm.model_executor.layers.fused_moe.experts.trtllm_nvfp4_moe import (
297 TrtLlmNvFp4ExpertsModular,
298 )
299
300 register_experts(
301 TrtLlmNvFp4ExpertsModular,
302 standard_format,
303 nvfp4_types,
304 blocked_quantization_support=False,
305 )
306
307 if has_flashinfer_trtllm_fused_moe() and current_platform.has_device_capability(100):
308 from vllm.model_executor.layers.fused_moe.experts.trtllm_fp8_moe import (
309 TrtLlmFp8ExpertsModular,
310 )
311
312 register_experts(
313 TrtLlmFp8ExpertsModular,
314 standard_format,
315 fp8_types,
316 blocked_quantization_support=True,
317 )
318
319 if has_aiter():
320 from vllm.model_executor.layers.fused_moe.experts.rocm_aiter_moe import (
321 AiterExperts,
322 )
323
324 register_experts(
325 AiterExperts,
326 standard_format,
327 # AiterExperts also supports the fully-unquantized (None, None)
328 # scheme (see SUPPORTED_W_A in rocm_aiter_moe.py), not just fp8.
329 common_float_types,
330 blocked_quantization_support=True,
331 needs_aiter=True,
332 )
333 else:
334 AiterExperts = None
335
336 if has_deep_gemm() and is_deep_gemm_supported():
337 register_experts(
338 BatchedDeepGemmExperts,
339 batched_format,
340 fp8_types,
341 blocked_quantization_support=True,
342 needs_matching_quant=False,
343 needs_deep_gemm=True,
344 )
345 register_experts(
346 DeepGemmExperts,
347 standard_format,
348 fp8_types,
349 blocked_quantization_support=True,
350 needs_matching_quant=False,
351 needs_deep_gemm=True,
352 )
353 register_experts(
354 TritonOrDeepGemmExperts,
355 standard_format,
356 common_float_and_int_types,
357 blocked_quantization_support=True,
358 needs_matching_quant=True,
359 needs_deep_gemm=True,
360 )
361
362 if cutlass_fp8_supported():
363 from vllm.model_executor.layers.fused_moe import (
364 CutlassBatchedExpertsFp8,
365 CutlassExpertsFp8,
366 )
367
368 register_experts(
369 CutlassExpertsFp8,
370 standard_format,
371 fp8_types,
372 blocked_quantization_support=False,
373 )
374 register_experts(
375 CutlassBatchedExpertsFp8,
376 batched_format,
377 fp8_types,
378 blocked_quantization_support=False,
379 )
380 else:
381 CutlassBatchedExpertsFp8 = None
382 CutlassExpertsFp8 = None
383
384 if cutlass_fp4_supported():
385 from vllm.model_executor.layers.fused_moe.experts.cutlass_moe import (
386 CutlassExpertsFp4,
387 )
388
389 register_experts(
390 CutlassExpertsFp4,
391 standard_format,
392 nvfp4_types,
393 blocked_quantization_support=True,
394 )
395 else:
396 CutlassExpertsFp4 = None
397
398 MK_QUANT_CONFIGS: list[TestMoEQuantConfig | None] = [
399 None,
400 # per-channel / per-column weights and per-tensor activations
401 TestMoEQuantConfig(
402 quant_dtype=current_platform.fp8_dtype(),
403 per_out_ch_quant=True,
404 per_act_token_quant=False,
405 block_shape=None,
406 ),
407 # per-channel / per-column weights and per-token activations
408 TestMoEQuantConfig(
409 quant_dtype=current_platform.fp8_dtype(),
410 per_out_ch_quant=True,
411 per_act_token_quant=True,
412 block_shape=None,
413 ),
414 # per-tensor weights and per-tensor activations
415 TestMoEQuantConfig(
416 quant_dtype=current_platform.fp8_dtype(),
417 per_out_ch_quant=False,
418 per_act_token_quant=False,
419 block_shape=None,
420 ),
421 # per-tensor weights and per-token activations
422 TestMoEQuantConfig(
423 quant_dtype=current_platform.fp8_dtype(),
424 per_out_ch_quant=False,
425 per_act_token_quant=True,
426 block_shape=None,
427 ),
428 # block-quantized weights and 128 block per-token activations
429 TestMoEQuantConfig(
430 quant_dtype=current_platform.fp8_dtype(),
431 per_out_ch_quant=False,
432 per_act_token_quant=False,
433 block_shape=[128, 128],
434 ),
435 # TODO (varun) : Should we test the following combinations ?
436 # block-quantized weights and per-token activations
437 # block-quantized weights and per-tensor activations
438 ]
439
440 if cutlass_fp4_supported() or has_flashinfer_cutlass_fused_moe():
441 MK_QUANT_CONFIGS += [
442 TestMoEQuantConfig(
443 quant_dtype="nvfp4",
444 per_out_ch_quant=False,
445 per_act_token_quant=False,
446 block_shape=None,
447 ),
448 ]
449
450
451 def make_fused_experts(
452 fused_experts_type: mk.FusedMoEExpertsModular,
453 moe: FusedMoEConfig,
454 quant_config: FusedMoEQuantConfig,
455 num_dispatchers: int,
456 N: int,
457 ) -> mk.FusedMoEExpertsModular:
458 if (
459 fused_experts_type.activation_format()
460 == mk.FusedMoEActivationFormat.BatchedExperts
461 ):
462 kwargs = {
463 "moe_config": moe,
464 "quant_config": quant_config,
465 "max_num_tokens": moe.max_num_tokens,
466 "num_dispatchers": num_dispatchers,
467 }
468 else:
469 kwargs = {
470 "moe_config": moe,
471 "quant_config": quant_config,
472 }
473
474 torch.set_printoptions(threshold=0, edgeitems=0, linewidth=10000)
475
476 print(f"Making {fused_experts_type.__class__.__name__} {kwargs} ...")
477 experts = fused_experts_type(**kwargs)
478
479 torch.set_printoptions(threshold=1000, edgeitems=5, linewidth=80)
480
481 return experts