mirror of
https://github.com/Comfy-Org/ComfyUI.git
synced 2026-08-28 03:37:31 +08:00
feat: Support MiniMax-H3 (CORE-375) (#15224)
This commit is contained in:
55
comfy/ops.py
55
comfy/ops.py
@@ -943,13 +943,61 @@ if CUBLAS_IS_AVAILABLE:
|
||||
# ==============================================================================
|
||||
# Mixed Precision Operations
|
||||
# ==============================================================================
|
||||
from . import quant_ops
|
||||
from .quant_ops import (
|
||||
QuantizedTensor,
|
||||
QUANT_ALGOS,
|
||||
TensorCoreFP8Layout,
|
||||
TensorWiseINT8Layout,
|
||||
get_layout_class,
|
||||
)
|
||||
|
||||
def _swiglu_eager(x):
|
||||
gate, up = x.chunk(2, dim=-1)
|
||||
return torch.nn.functional.silu(gate).mul_(up)
|
||||
|
||||
|
||||
INPUT_ACT_EAGER = {
|
||||
"gelu_tanh": lambda x: torch.nn.functional.gelu(x, approximate="tanh"),
|
||||
"swiglu": _swiglu_eager,
|
||||
}
|
||||
|
||||
|
||||
def linear_input_act(linear, x, input_act):
|
||||
"""``linear(act(x))``, with ``act`` folded into an INT8 activation quantizer.
|
||||
|
||||
An INT8 linear quantizes its input anyway, so an elementwise activation can
|
||||
ride along inside that kernel instead of writing a full-size intermediate to
|
||||
HBM and reading it straight back. Worth it for an MLP's down-projection,
|
||||
where the intermediate is several times the hidden size.
|
||||
|
||||
"""
|
||||
weight = linear.weight
|
||||
if (comfy.model_management.in_training
|
||||
or not isinstance(weight, QuantizedTensor)
|
||||
or weight._layout_cls != "TensorWiseINT8Layout"
|
||||
or getattr(weight._params, "transposed", False)):
|
||||
return linear(INPUT_ACT_EAGER[input_act](x))
|
||||
|
||||
# want_requant keeps a vbar-streamed layer on the INT8 path when a LoRA is
|
||||
# patched in on the fly; without it the cast hands back a dequantized weight.
|
||||
weight, bias, offload_stream = cast_bias_weight(
|
||||
linear, x, offloadable=True, compute_dtype=x.dtype, want_requant=True)
|
||||
try:
|
||||
if not isinstance(weight, QuantizedTensor):
|
||||
# A LoRA weight_function, or activations whose dtype differs from the
|
||||
# weight's, make the cast hand back a dequantized tensor.
|
||||
return torch.nn.functional.linear(INPUT_ACT_EAGER[input_act](x), weight, bias)
|
||||
qdata, scale = TensorWiseINT8Layout.get_plain_tensors(weight)
|
||||
return quant_ops.ck.int8_linear(
|
||||
x, qdata, scale, bias, x.dtype,
|
||||
convrot=getattr(weight._params, "convrot", False),
|
||||
convrot_groupsize=getattr(weight._params, "convrot_groupsize", 256),
|
||||
input_act=input_act,
|
||||
)
|
||||
finally:
|
||||
uncast_bias_weight(linear, weight, bias, offload_stream)
|
||||
|
||||
|
||||
class QuantLinearFunc(torch.autograd.Function):
|
||||
"""Custom autograd function for quantized linear: quantized forward, optionally FP8 backward.
|
||||
@@ -1259,7 +1307,7 @@ def mixed_precision_ops(quant_config={}, compute_dtype=torch.bfloat16, full_prec
|
||||
|
||||
def state_dict(self, *args, destination=None, prefix="", **kwargs):
|
||||
sd = destination if destination is not None else {}
|
||||
return _quantized_weight_state_dict(self, sd, prefix, extra_quant_params=("input_scale",))
|
||||
return _quantized_weight_state_dict(self, sd, prefix, extra_quant_params=("input_scale", "pre_quant_scale"))
|
||||
|
||||
def _forward(self, input, weight, bias):
|
||||
return torch.nn.functional.linear(input, weight, bias)
|
||||
@@ -1298,6 +1346,11 @@ def mixed_precision_ops(quant_config={}, compute_dtype=torch.bfloat16, full_prec
|
||||
def forward(self, input, *args, **kwargs):
|
||||
run_every_op()
|
||||
|
||||
# ModelOpt AWQ-style smoothing
|
||||
pre_quant_scale = getattr(self, 'pre_quant_scale', None)
|
||||
if pre_quant_scale is not None:
|
||||
input = input * comfy.model_management.cast_to_device(pre_quant_scale, input.device, input.dtype)
|
||||
|
||||
input_shape = input.shape
|
||||
reshaped_nd = False
|
||||
#If cast needs to apply lora, it should be done in the compute dtype
|
||||
|
||||
Reference in New Issue
Block a user