Diffusers 中使用 Quanto 后端进行模型量化:配置、实战与源码原理
发布时间:2026/9/12 21:16:21来源:尧图网络
Diffusers 中使用 Quanto 后端进行模型量化配置、实战与源码原理【免费下载链接】diffusers Diffusers: State-of-the-art diffusion models for image, video, and audio generation in PyTorch.项目地址: https://gitcode.com/GitHub_Trending/di/diffusers导读Quantooptimum-quanto是 HuggingFace Optimum 生态中的轻量级 PyTorch 量化后端本指南围绕 Diffusers 仓库中 docs/source/en/quantization/quanto.md 展开讲解如何通过QuantoConfig在from_pretrained/from_single_file加载流程中对扩散模型以 FLUX.1 的 Transformer 为例进行 float8/int8/int4/int2 权重量化并深入源码解读其实现机制、保存与torch.compile集成的具体前提。读完本文你将掌握在 Diffusers 中一键量化、局部跳过、保存复用量化模型及规避已知限制的完整实战方案。[!WARNING] 根据 quanto.md 与 quanto_quantizer.py 中的说明Quanto 后端已弃用deprecated并将在 Diffusers 1.0.0 版本中移除。新项目建议优先考虑 bitsandbytes 或 torchao 后端。本文内容仅面向仍在使用或需要维护既有 Quanto 量化流程的开发者。Quanto 后端的定位与设计特性Quanto 是面向 Optimum 生态的 PyTorch 量化后端设计目标是通用versatility与简单simplicity。其核心特性如下Eager 模式可用所有功能在 eager 模式下即可工作无需模型可被 trace兼容各种自定义结构的模型支持量化感知训练QAT量化模块可继续参与训练或微调兼容torch.compile量化后的模型可与 PyTorch 编译优化配合使用当前 Diffusers 集成中仅限 int8 权重详见下文设备无关量化模型可在 CUDA、XPU、MPS、CPU 等不同设备上运行。在 Diffusers 的量化后端体系中Quanto 通过 AUTO_QUANTIZER_MAPPING 中的quanto: QuantoQuantizer注册对应的配置类为 AUTO_QUANTIZATION_CONFIG_MAPPING 中的quanto: QuantoConfig。加载模型时modeling_utils.py 会通过DiffusersAutoQuantizer.from_config自动实例化正确的量化器并执行量化流程对用户而言只需传递一个配置对象即可。环境安装与版本要求使用 Quanto 后端需要安装两个依赖pip install optimum-quanto accelerate其中optimum-quanto有明确的最低版本要求。在 quanto_quantizer.py 的validate_environment方法中未安装optimum-quanto时抛出 ImportError版本低于0.2.6时抛出ImportError提示Loading an optimum-quanto quantized model requiresoptimum-quanto0.2.6未安装accelerate时同样抛出 ImportError。此外量化器类的required_packages [quanto, accelerate]quanto_quantizer.py也印证了这两个依赖是硬性要求。建议同时将accelerate升级到0.27.0因为该版本起才提供CustomDtype.FP8 / INT4 / INT2等自定义 dtype 映射见下文adjust_target_dtype说明。核心用法在from_pretrained中一键量化Quanto 的接入方式是典型的零改造构造一个QuantoConfig对象将其作为quantization_config参数传给from_pretrained()即可。以 FLUX.1-dev 的 Transformer 组件为例import torch from diffusers import FluxTransformer2DModel, QuantoConfig model_id black-forest-labs/FLUX.1-dev quantization_config QuantoConfig(weights_dtypefloat8) transformer FluxTransformer2DModel.from_pretrained( model_id, subfoldertransformer, quantization_configquantization_config, dtypetorch.bfloat16, ) pipe FluxPipeline.from_pretrained(model_id, transformertransformer, dtypetorch.bfloat16) pipe.to(cuda) # 或 mps、xpu、cpu prompt A cat holding a sign that says hello world image pipe( prompt, num_inference_steps50, guidance_scale4.5, max_sequence_length512 ).images[0] image.save(output.png)几个关键点量化只作用于Transformer 组件加载时传入subfoldertransformer定位 FLUX.1 仓库中的子目录权重其余组件文本编码器、VAE、调度器由FluxPipeline正常加载配合dtypetorch.bfloat16可同时享受低精度权重量化与低精度计算bf16的双重收益量化后的 Transformer 通过pipe.to(cuda)迁移到目标设备由于 Quanto 量化权重是设备无关的cuda/mps/xpu/cpu均可用。从源码调用链看from_pretrained内部会依次执行validate_environment环境与版本校验→preprocess_modelbase.py 中调用_process_model_before_weight_loading完成模块替换并标记model.is_quantized True→ 权重加载 →postprocess_model。对 Quanto 而言模块替换发生在 utils.py 的_replace_with_quanto_layers中。QuantoConfig 参数详解QuantoConfig定义在 quantization_config.py是QuantizationConfigMixin的子类通过quant_method QuantizationMethod.QUANTO标识自身后端。它的全部参数如下参数类型默认值说明weights_dtypestrint8权重量化后的目标 dtype仅支持float8、int8、int4、int2四种取值post_init会做合法性校验传入其他值将抛出ValueErrormodules_to_not_convertlist[str]None不参与量化的模块名列表用于保留某些模块的原始精度例如 Whisper encoder、Llava encoder、Mixtral 的 gate 层等场景weights_dtype与底层量化类型的对应关系可在 utils.py 中看到def _get_weight_type(dtype: str): return {float8: qfloat8, int8: qint8, int4: qint4, int2: qint2}[dtype]即float8→qfloat8、int8→qint8、int4→qint4、int2→qint2。量化范围仅限nn.Linear权重虽然 Quanto 库本身支持量化nn.Conv2d和nn.LayerNorm等模块但当前 Diffusers 集成只量化模型中的nn.Linear层权重。这一点在 utils.py 的实现中体现得很明确——递归遍历时仅对isinstance(module, nn.Linear)的模块执行替换将其换为optimum.quanto.QLinearif isinstance(module, nn.Linear): with init_empty_weights(): qlinear QLinear( in_featuresmodule.in_features, out_featuresmodule.out_features, biasmodule.bias is not None, dtypemodule.weight.dtype, weights_get_weight_type(quantization_config.weights_dtype), ) model._modules[name] qlinear model._modules[name].source_cls type(module) model._modules[name].requires_grad_(False)同时替换完成后会检查是否真的发生了替换utils.pyhas_been_replaced any(isinstance(replaced_module, QLinear) for _, replaced_module in model.named_modules()) if not has_been_replaced: logger.warning( f{model.__class__.__name__} does not appear to have any nn.Linear modules. Quantization will not be applied. ... )也就是说如果一个模型架构里没有任何nn.Linear层量化将静默无效并输出告警——这是排查量化后没效果问题时的关键线索。权重 dtype 到加载 dtype 的映射在QuantoQuantizer.adjust_target_dtypequanto_quantizer.py中accelerate0.27.0时会将weights_dtype映射为 accelerate 的CustomDtype确保权重以正确的低精度格式挂载到 meta 设备上mapping { int8: torch.int8, float8: CustomDtype.FP8, int4: CustomDtype.INT4, int2: CustomDtype.INT2, } target_dtype mapping[self.quantization_config.weights_dtype]这也解释了为何 int4/int2 这类非 PyTorch 原生 dtype 也能被 accelerate 正确识别和装载。跳过特定模块的量化某些模块可能对精度极其敏感需要保留原始精度。通过QuantoConfig的modules_to_not_convert参数即可跳过import torch from diffusers import FluxTransformer2DModel, QuantoConfig model_id black-forest-labs/FLUX.1-dev quantization_config QuantoConfig( weights_dtypefloat8, modules_to_not_convert[proj_out], # 例如 FLUX Transformer 的输出投影层 ) transformer FluxTransformer2DModel.from_pretrained( model_id, subfoldertransformer, quantization_configquantization_config, dtypetorch.bfloat16, )使用该参数时务必注意模块名必须与state_dict中的键名一致即传入的是model.named_modules()所暴露的层级名如proj_out、transformer_blocks.0.attn.to_q等否则匹配不上会导致该模块仍然被量化在_process_model_before_weight_loadingquanto_quantizer.py中modules_to_not_convert会被归一化为 list并与 Diffusers 侧的keep_in_fp32_modules合并一起传给_replace_with_quanto_layers对应的替换逻辑在 utils.py遍历到名字命中列表的模块时直接continue不执行 QLinear 替换。使用from_single_file加载原始权重并量化QuantoConfig同样兼容FromOriginalModelMixin.from_single_file适用于只有一个.safetensors原始权重文件的场景如 FLUX.1 的flux1-dev.safetensorsimport torch from diffusers import FluxTransformer2DModel, QuantoConfig ckpt_path https://huggingface.co/black-forest-labs/FLUX.1-dev/blob/main/flux1-dev.safetensors quantization_config QuantoConfig(weights_dtypefloat8) transformer FluxTransformer2DModel.from_single_file( ckpt_path, quantization_configquantization_config, dtypetorch.bfloat16, )该方式与from_pretrained的区别在于权重来源是单文件原始 checkpoint 而非 Diffusers 目录结构但量化配置的传递方式完全一致量化流程同样经过QuantoQuantizer的预处理。保存与重新加载量化模型Diffusers 支持通过ModelMixin.save_pretrained将 Quanto 量化模型序列化保存import torch from diffusers import FluxTransformer2DModel, QuantoConfig model_id black-forest-labs/FLUX.1-dev quantization_config QuantoConfig(weights_dtypefloat8) transformer FluxTransformer2DModel.from_pretrained( model_id, subfoldertransformer, quantization_configquantization_config, dtypetorch.bfloat16, ) # 保存量化模型以便复用 transformer.save_pretrained(your quantized model save path) # 之后可以直接重新加载量化模型 model FluxTransformer2DModel.from_pretrained(your quantized model save path)在保存时modeling_utils.py 会检查hf_quantizer.is_serializable与supports_safetensors_serialization而QuantoQuantizer的is_serializable属性返回Truequanto_quantizer.py因此保存链路是通的。加载时保存目录中的quantization_config会被 modeling_utils.py 检测到自动走预量化pre_quantized路径并先对模型执行freeze()以对齐 state_dictutils.py。关键限制与 Quanto 库直出的模型不互通官方文档明确强调用 Quanto 库直接量化得到的模型目前无法通过 Diffusers 的from_pretrained加载。原因在于两者的序列化与加载约定不同经 Diffusers Quanto 后端量化保存的模型携带 Diffusers 约定的quantization_config含quant_method: quanto与冻结后的状态字典直接用optimum.quanto量化产生的模型缺乏这套配置元数据DiffusersAutoQuantizer.from_pretrained在 auto.py 中会因为找不到quantization_config而抛出ValueError。因此若需要在 Diffusers 中复用量化模型务必通过 Diffusers 自身的save_pretrained保存而不是复用 Quanto 库的序列化产物。结合torch.compile加速推理Quanto 后端支持与torch.compile组合但当前仅限int8权重量化类型import torch from diffusers import FluxPipeline, FluxTransformer2DModel, QuantoConfig model_id black-forest-labs/FLUX.1-dev quantization_config QuantoConfig(weights_dtypeint8) transformer FluxTransformer2DModel.from_pretrained( model_id, subfoldertransformer, quantization_configquantization_config, dtypetorch.bfloat16, ) transformer torch.compile(transformer, modemax-autotune, fullgraphTrue) pipe FluxPipeline.from_pretrained( model_id, transformertransformer, dtypetorch.bfloat16 ) pipe.to(cuda) # 或 mps、xpu、cpu images pipe(A cat holding a sign that says hello).images[0] images.save(flux-quanto-compile.png)QuantoQuantizer.is_compileable属性返回Truequanto_quantizer.py与量化模型兼容torch.compile的设计目标一致。实操建议编译前先做一次 warmup 推理避免首轮编译开销计入耗时统计modemax-autotune适合追求极致性能的场景但编译时间更长。支持的量化类型一览Weights权重权重类型说明accelerate dtype 映射float88 位浮点精度损失小FLUX 实战示例的默认推荐CustomDtype.FP8int88 位整数唯一支持torch.compile的类型torch.int8int44 位整数压缩比更高CustomDtype.INT4int22 位整数压缩比最高精度损失最大CustomDtype.INT2选择建议追求画质与速度平衡用float8需要与torch.compile联动用int8显存极度紧张时可尝试int4/int2并配合提示词与步数调整补偿画质。由于本文所述 Diffusers 集成仅量化nn.Linear权重实际显存收益取决于目标模型中 Linear 层权重的占比。底层实现与调用链小结为了帮助读者在仓库中继续深入这里汇总与 Quanto 后端相关的核心文件与职责文件职责quantization_config.pyQuantoConfig定义weights_dtype、modules_to_not_convert参数与合法性校验quanto_quantizer.pyQuantoQuantizer环境校验、模块替换入口、dtype 映射、显存预算调整、可训练/可序列化/可编译标记utils.py_replace_with_quanto_layers将nn.Linear替换为QLinear并冻结权重auto.py将quanto映射到QuantoQuantizer与QuantoConfigmodeling_utils.pyfrom_pretrained中量化配置的合并、量化器实例化与validate_environment调用base.pyDiffusersQuantizer基类的预处理/后处理流程骨架几个值得注意的实现细节显存预算自动缩减adjust_max_memoryquanto_quantizer.py会将传入的max_memory各设备预算统一乘以 0.90为量化过程预留 10% 余量多卡限制validate_environment中明确拒绝多 GPU 推理或 CPU/disk offload场景——若device_map为 dict 且键数大于 1会抛出ValueErrorquanto_quantizer.py。因此 Quanto 后端目前只支持单设备单卡或纯 CPU/单 XPU 等加载可训练性is_trainable返回True配合 Quanto 的量化感知训练QAT能力量化模型可继续参与微调替换后的QLinear权重requires_grad_(False)训练时依赖 Quanto 的freeze/unfreeze机制管理缺失键处理update_missing_keys会剔除 QModule 内部的非weight/bias键避免加载预量化模型时因键名差异报错quanto_quantizer.py。已知限制与迁移建议结合文档与源码使用 Quanto 后端前请确认以下几点生命周期Quanto 后端已弃用将在 Diffusers 1.0.0 移除加载时也会触发deprecate警告长期项目建议评估迁移到 bitsandbytes4/8 位、load_in_4bit等或 torchao量化范围仅nn.Linear权重卷积等模块不会被量化设备映射不支持多 GPU / CPU offload 的device_map互操作Quanto 库直接量化的模型无法通过 Diffusersfrom_pretrained加载必须使用 Diffusers 的save_pretrained产物编译范围torch.compile仅适配int8权重。在做出选择前可以对照 量化总览文档 了解 Diffusers 支持的全部后端bitsandbytes_4bit、bitsandbytes_8bit、gguf、quanto、torchao、modelopt、auto-round、nunchaku_lite、sdnq及其适用场景再结合本文的 Quanto 细节为你的模型部署方案做出准确的技术选型。【免费下载链接】diffusers Diffusers: State-of-the-art diffusion models for image, video, and audio generation in PyTorch.项目地址: https://gitcode.com/GitHub_Trending/di/diffusers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网