main
py 169 lines 5.37 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 from abc import ABC, abstractmethod
5
6 import torch
7
8 import vllm.model_executor.layers.fused_moe.modular_kernel as mk
9 from vllm.model_executor.layers.fused_moe.activation import MoEActivation
10 from vllm.model_executor.layers.fused_moe.config import FusedMoEParallelConfig
11 from vllm.model_executor.layers.quantization.utils.quant_utils import QuantKey
12
13
14 class FallbackExperts(mk.FusedMoEExpertsModular, ABC):
15 """Base class for runtime dispatching of expert implementations."""
16
17 def __init__(
18 self,
19 experts: mk.FusedMoEExpertsModular,
20 fallback_experts: mk.FusedMoEExpertsModular,
21 ):
22 super().__init__(
23 moe_config=experts.moe_config, quant_config=experts.quant_config
24 )
25 self.fallback_experts = fallback_experts
26 self.experts = experts
27
28 @staticmethod
29 def get_clses() -> tuple[
30 type[mk.FusedMoEExpertsModular],
31 type[mk.FusedMoEExpertsModular],
32 ]:
33 """Get the cls for the experts and fallback experts.
34
35 Subclasses should implement this method, so that
36 we have a consistent way to call the _supports_*
37 class methods below.
38 """
39 raise NotImplementedError(
40 "Subclasses must return the cls for the experts and fallback experts."
41 )
42
43 @classmethod
44 def activation_format(
45 cls: type["FallbackExperts"],
46 ) -> mk.FusedMoEActivationFormat:
47 experts_cls, fallback_cls = cls.get_clses()
48 assert experts_cls.activation_format() == fallback_cls.activation_format()
49 return experts_cls.activation_format()
50
51 @classmethod
52 def _supports_current_device(cls) -> bool:
53 experts_cls, fallback_cls = cls.get_clses()
54 return (
55 experts_cls._supports_current_device()
56 and fallback_cls._supports_current_device()
57 )
58
59 @classmethod
60 def _supports_no_act_and_mul(cls) -> bool:
61 experts_cls, fallback_cls = cls.get_clses()
62 return (
63 experts_cls._supports_no_act_and_mul()
64 and fallback_cls._supports_no_act_and_mul()
65 )
66
67 @classmethod
68 def _supports_quant_scheme(
69 cls,
70 weight_key: QuantKey | None,
71 activation_key: QuantKey | None,
72 ) -> bool:
73 experts_cls, fallback_cls = cls.get_clses()
74 return experts_cls._supports_quant_scheme(
75 weight_key, activation_key
76 ) and fallback_cls._supports_quant_scheme(weight_key, activation_key)
77
78 @classmethod
79 def _supports_activation(cls, activation: MoEActivation) -> bool:
80 experts_cls, fallback_cls = cls.get_clses()
81 return experts_cls._supports_activation(
82 activation
83 ) and fallback_cls._supports_activation(activation)
84
85 @classmethod
86 def _supports_parallel_config(
87 cls, moe_parallel_config: FusedMoEParallelConfig
88 ) -> bool:
89 experts_cls, fallback_cls = cls.get_clses()
90 return experts_cls._supports_parallel_config(
91 moe_parallel_config
92 ) and fallback_cls._supports_parallel_config(moe_parallel_config)
93
94 def finalize_weight_and_reduce_impl(self) -> mk.TopKWeightAndReduce:
95 e_war = self.experts.finalize_weight_and_reduce_impl()
96 fbe_war = self.fallback_experts.finalize_weight_and_reduce_impl()
97 is_dge_war = e_war is not None
98 is_fbe_war = fbe_war is not None
99
100 if is_dge_war and is_fbe_war:
101 assert e_war == fbe_war, (
102 "Both implementations should agree on WeightAndReduce impls. "
103 f"Got e_war: {e_war}, and fbe_war: {fbe_war}"
104 )
105
106 if e_war is not None:
107 return e_war
108 assert fbe_war is not None
109 return fbe_war
110
111 @abstractmethod
112 def workspace_shapes(
113 self,
114 M: int,
115 N: int,
116 K: int,
117 topk: int,
118 global_num_experts: int,
119 local_num_experts: int,
120 expert_tokens_meta: mk.ExpertTokensMetadata | None,
121 activation: MoEActivation,
122 ) -> tuple[tuple[int, ...], tuple[int, ...], tuple[int, ...]]:
123 raise NotImplementedError
124
125 @abstractmethod
126 def _select_experts_impl(
127 self,
128 hidden_states: torch.Tensor,
129 w1: torch.Tensor,
130 w2: torch.Tensor,
131 ) -> mk.FusedMoEExpertsModular:
132 raise NotImplementedError
133
134 def apply(
135 self,
136 output: torch.Tensor,
137 hidden_states: torch.Tensor,
138 w1: torch.Tensor,
139 w2: torch.Tensor,
140 topk_weights: torch.Tensor,
141 topk_ids: torch.Tensor,
142 activation: MoEActivation,
143 global_num_experts: int,
144 expert_map: torch.Tensor | None,
145 a1q_scale: torch.Tensor | None,
146 a2_scale: torch.Tensor | None,
147 workspace13: torch.Tensor,
148 workspace2: torch.Tensor,
149 expert_tokens_meta: mk.ExpertTokensMetadata | None,
150 apply_router_weight_on_input: bool,
151 ):
152 experts = self._select_experts_impl(hidden_states, w1, w2)
153 experts.apply(
154 output,
155 hidden_states,
156 w1,
157 w2,
158 topk_weights,
159 topk_ids,
160 activation,
161 global_num_experts,
162 expert_map,
163 a1q_scale,
164 a2_scale,
165 workspace13,
166 workspace2,
167 expert_tokens_meta,
168 apply_router_weight_on_input,
169 )