|
class _QuantGptOssExperts(_QuantFunctionalMixin): |
|
"""Quantized wrapper for `transformers.GptOssExperts`. |
|
|
|
Quantizes `gate_up_proj` and `down_proj` weights via dynamic attributes inside `quantize_weight()`. |
|
Activations into `gate_up_proj` are quantized by `gate_up_proj_input_quantizer`. For `down_proj` |
|
activation quantization, we intercept `torch.Tensor.__matmul__`/`torch.bmm` and quantize inputs |
|
on every second call (since the first call computes `gate_up_proj` outputs and second call |
|
computes `down_proj` outputs). |
|
""" |
|
|
|
@staticmethod |
|
def _get_quantized_weight(quantizer, module, weight): |
|
# MoE weight is accessed for each expert in one forward pass. so lets cache it |
|
if module._enable_weight_quantization: |
|
if hasattr(quantizer, "_cached_quant_val"): |
|
return getattr(quantizer, "_cached_quant_val") |
|
quantizer._cached_quant_val = _transposed_quantize(weight, quantizer) |
|
return quantizer._cached_quant_val |
|
return weight |
|
|
|
def _setup_for_weight_quantization(self): |
|
self._register_dynamic_attribute( |
|
"gate_up_proj", partial(self._get_quantized_weight, self.gate_up_proj_weight_quantizer) |
|
) |
|
self._register_dynamic_attribute( |
|
"down_proj", partial(self._get_quantized_weight, self.down_proj_weight_quantizer) |
|
) |
|
|
|
def _setup(self): |
|
assert not hasattr(self, "kernel_layer_name"), ( |
|
"ModelOpt quantization does not support patched forward for kernel_hub" |
|
) |
|
self.gate_up_proj_input_quantizer = TensorQuantizer() |
|
self.gate_up_proj_weight_quantizer = TensorQuantizer() |
|
self.down_proj_input_quantizer = TensorQuantizer() |
|
self.down_proj_weight_quantizer = TensorQuantizer() |
|
|
|
self._register_temp_attribute("_enable_weight_quantization", False) |
|
self._register_temp_attribute("_down_proj_mul", False) |
|
self._setup_for_weight_quantization() |
|
|
|
@property |
|
def functionals_to_replace(self): |
|
def _quantized_bmm(batch1, batch2): |
|
batch1 = self.down_proj_input_quantizer(batch1) if self._down_proj_mul else batch1 |
|
self._down_proj_mul = not self._down_proj_mul # toggle the flag |
|
return torch._bmm(batch1, batch2) |
|
|
|
def _tensor_matmul(self_t, other): |
|
self_t = self.down_proj_input_quantizer(self_t) if self._down_proj_mul else self_t |
|
self._down_proj_mul = not self._down_proj_mul |
|
return torch.matmul(self_t, other) |
|
|
|
return [ |
|
(torch, "bmm", _quantized_bmm), |
|
(torch.Tensor, "__matmul__", _tensor_matmul), |
|
] |
|
|
|
@contextmanager |
|
def quantize_weight(self): |
|
"""Context in which MoE weight is quantized.""" |
|
self._enable_weight_quantization = True |
|
try: |
|
yield |
|
finally: |
|
for module in self.modules(): |
|
if isinstance(module, TensorQuantizer) and hasattr(module, "_cached_quant_val"): |
|
delattr(module, "_cached_quant_val") |
|
self._enable_weight_quantization = False |
|
|
|
def forward( |
|
self, hidden_states: torch.Tensor, router_indices=None, routing_weights=None |
|
) -> torch.Tensor: |
|
"""Forward method to add quantization.""" |
|
hidden_states = self.gate_up_proj_input_quantizer(hidden_states) |
|
with self.quantize_weight(): |
|
return super().forward(hidden_states, router_indices, routing_weights) |
|
|
|
|
|
try: |
|
from transformers.models.gpt_oss.modeling_gpt_oss import GptOssExperts |
|
|
|
if GptOssExperts not in QuantModuleRegistry: |
|
QuantModuleRegistry.register({GptOssExperts: "hf.GptOssExperts"})(_QuantGptOssExperts) |
|
except ImportError: |
|
pass |
Hello team,
I've been looking into quantizing some of the recent models (GLM-4.x, Minimax-M2.1, MiMo-V2-Flash, ...) but it seems like most frameworks do not forward calibration data to all experts unless the model is added to the quantization framework.
This can lead to significant quality issues like https://avtc.github.io/aquarium-side-by-side/ (discussion ModelCloud/GPTQModel#2235 (comment)):
Looking at the repo, I see all expert calibration mentioned in 2 places:
Model-Optimizer/examples/deepseek/ptq.py
Lines 210 to 219 in 3350b0a
Model-Optimizer/modelopt/torch/quantization/plugins/huggingface.py
Lines 346 to 368 in 3350b0a
However in the latter case, only a handful of models are supported:
Model-Optimizer/modelopt/torch/quantization/plugins/huggingface.py
Lines 504 to 577 in 3350b0a
And some like gpt-oss or DeepSeek need mid to significant customization.
Can you provide guidance, ideally a reference documentation on how to add support to optimally quantize new MoE models to your framework?
In particular this should cover:
_QuantSparseMoeis enough, for example I think Minimax-M2.1 is in this caseModel-Optimizer/modelopt/torch/quantization/plugins/huggingface.py
Lines 580 to 665 in 3350b0a
trust_remote_codelike Minimax-M2.x Add support for MiniMax-M2 huggingface/transformers#42028