@@ -1287,14 +1287,24 @@ def _quantized_weight_state_dict(module, sd, prefix, extra_quant_conf=None, extr
12871287 return sd
12881288
12891289
1290+ class MixedPrecisionOp (CastWeightBiasOp ):
1291+ quant_format = None
1292+
1293+ def can_use_quantized_matmul (self , disabled_formats ):
1294+ return (self .quant_format in QUANT_ALGOS
1295+ and not self ._full_precision_mm_config
1296+ and self .quant_format not in self ._disabled_formats
1297+ and self .quant_format not in disabled_formats )
1298+
1299+
12901300def mixed_precision_ops (quant_config = {}, compute_dtype = torch .bfloat16 , full_precision_mm = False , disabled = []):
12911301 class MixedPrecisionOps (manual_cast ):
12921302 _quant_config = quant_config
12931303 _compute_dtype = compute_dtype
12941304 _full_precision_mm = full_precision_mm
12951305 _disabled = disabled
12961306
1297- class Linear (torch .nn .Module , CastWeightBiasOp ):
1307+ class Linear (torch .nn .Module , MixedPrecisionOp ):
12981308 _disabled_formats = disabled
12991309
13001310 def __init__ (self , in_features : int , out_features : int , bias : bool = True , device = None , dtype = None ):
@@ -1342,8 +1352,7 @@ def forward_comfy_cast_weights(
13421352 compute_dtype = compute_dtype ,
13431353 want_requant = want_requant ,
13441354 ) as (weight , bias ):
1345- if isinstance (weight , QuantizedTensor ) and (self ._full_precision_mm_config or getattr (self , "quant_format" , None ) in self ._disabled_formats or not weight .layout_cls .supports_fast_matmul ()):
1346- # explicit per-layer full precision, or a format this device can't run: don't reach the fast quantized matmul
1355+ if self ._full_precision_mm and isinstance (weight , QuantizedTensor ):
13471356 weight = weight .dequantize ()
13481357 return self ._forward (input , weight , bias )
13491358
@@ -1447,7 +1456,7 @@ def set_weight(self, weight, inplace_update=False, seed=None, return_weight=Fals
14471456 def _apply (self , fn , recurse = True ): # This is to get torch.compile + moving weights to another device working
14481457 return _quantized_apply (self , fn , recurse )
14491458
1450- class MoEExperts (torch .nn .Module , CastWeightBiasOp ):
1459+ class MoEExperts (torch .nn .Module , MixedPrecisionOp ):
14511460 """Container for E quantized expert weights, indexed via expert_weight(i).
14521461
14531462 The bank lives on self.weight as a single 3D tensor — either a
@@ -1651,29 +1660,45 @@ def forward_comfy_cast_weights(self, input, out_dtype=None):
16511660
16521661 return MixedPrecisionOps
16531662
1654- def pick_operations (weight_dtype , compute_dtype , load_device = None , disable_fast_fp8 = False , fp8_optimizations = False , model_config = None ):
1655- fp8_compute = comfy .model_management .supports_fp8_compute (load_device ) # TODO: if we support more ops this needs to be more granular
1656- nvfp4_compute = comfy .model_management .supports_nvfp4_compute (load_device )
1657- mxfp8_compute = comfy .model_management .supports_mxfp8_compute (load_device )
1658- int8_compute = comfy .model_management .supports_int8_compute (load_device )
1663+ def get_disabled_quant_formats (device = None ):
1664+ disabled = set ()
1665+ if not comfy .model_management .supports_nvfp4_compute (device ):
1666+ disabled .add ("nvfp4" )
1667+ if not comfy .model_management .supports_mxfp8_compute (device ):
1668+ disabled .add ("mxfp8" )
1669+ if not comfy .model_management .supports_fp8_compute (device ):
1670+ disabled .add ("float8_e4m3fn" )
1671+ disabled .add ("float8_e5m2" )
1672+ if not comfy .model_management .supports_int8_compute (device ):
1673+ disabled .add ("int8_tensorwise" )
1674+ disabled .add ("convrot_w4a4" )
1675+ disabled .add ("asym_w4a8_int8" )
1676+ return disabled
1677+
1678+
1679+ @contextlib .contextmanager
1680+ def use_quantized_matmul (model , device ):
1681+ disabled = get_disabled_quant_formats (device )
1682+ previous = []
1683+ try :
1684+ for module in model .modules ():
1685+ if isinstance (module , MixedPrecisionOp ) and module .can_use_quantized_matmul (disabled ):
1686+ previous .append ((module , module ._full_precision_mm ))
1687+ module ._full_precision_mm = False
1688+ yield
1689+ finally :
1690+ for module , full_precision_mm in previous :
1691+ module ._full_precision_mm = full_precision_mm
16591692
1693+
1694+ def pick_operations (weight_dtype , compute_dtype , load_device = None , disable_fast_fp8 = False , fp8_optimizations = False , model_config = None ):
16601695 if model_config and hasattr (model_config , 'quant_config' ) and model_config .quant_config :
16611696 logging .info ("Using mixed precision operations" )
1662- disabled = set ()
1663- if not nvfp4_compute :
1664- disabled .add ("nvfp4" )
1665- if not mxfp8_compute :
1666- disabled .add ("mxfp8" )
1667- if not fp8_compute :
1668- disabled .add ("float8_e4m3fn" )
1669- disabled .add ("float8_e5m2" )
1670- if not int8_compute :
1671- disabled .add ("int8_tensorwise" )
1672- disabled .add ("convrot_w4a4" )
1673- disabled .add ("asym_w4a8_int8" )
1697+ disabled = get_disabled_quant_formats (load_device )
16741698 logging .info ("Native ops: {} {}" .format (", " .join (QUANT_ALGOS .keys () - disabled ), ", emulated ops: {}" .format (", " .join (disabled )) if len (disabled ) > 0 else "" ))
16751699 return mixed_precision_ops (model_config .quant_config , compute_dtype , disabled = disabled )
16761700
1701+ fp8_compute = comfy .model_management .supports_fp8_compute (load_device )
16771702 if (
16781703 fp8_compute and
16791704 (fp8_optimizations or PerformanceFeature .Fp8MatrixMultiplication in args .fast ) and
0 commit comments