Diffusion模型量化#
AngelSlim 提供高效灵活的 Diffusion Transformer (DiT) 模型 FP8 量化能力。通过少量校准数据(无需训练)实现模型压缩,提升推理效率并降低部署门槛。
支持的量化类型#
AngelSlim 支持以下四种 FP8 量化策略:
fp8-per-tensor:全局 per-tensor 量化(推荐,速度/精度平衡最佳)
fp8-per-tensor-weight-only:仅对权重量化(权重:FP8,激活仍为 BF16/FP16),适合对精度有更高要求的场景
fp8-per-block:支持 per-block 量化,适用于 NVIDIA Hopper (SM90+) 架构,block_size目前只支持128
fp8-per-token:精细的 per-token 量化,对多样输入有更强适应性
fp8-per-token-sgl:基于 SGL kernel 的 per-token 量化,使用优化的 CUDA kernel 实现更高效的 per-token 量化和矩阵乘法运算
可选依赖安装#
deep_gemm(用于 fp8-per-block)#
fp8-per-block 量化在启用 native_fp8_support 时需要安装 deep_gemm:
git clone --recursive https://github.com/deepseek-ai/DeepGEMM.git
cd DeepGEMM
./develop.sh
./install.sh
sgl_kernel(用于 fp8-per-token-sgl)#
fp8-per-token-sgl 量化需要安装 sgl_kernel:
pip install sgl-kernel==0.3.18
配置#
DynamicDiTQuantizer 类提供灵活的配置选项,您可以通过以下参数自定义量化行为:
构造函数参数#
quant_type(str):量化类型,可选值 “fp8-per-tensor”、”fp8-per-tensor-weight-only”、”fp8-per-block”、”fp8-per-token”、”fp8-per-token-sgl”include_patterns(List[str|re.Pattern], 可选):指定需要量化的层名称模式,支持字符串或正则表达式exclude_patterns(List[str|re.Pattern], 可选):指定需要排除的层名称模式,支持字符串或正则表达式layer_filter(Callable, 可选):自定义层筛选函数(高级自定义场景专用)native_fp8_support(bool, 可选):是否启用原生FP8硬件加速(自动检测,默认None)
主要方法#
convert_linear(model, scale=None):对模型指定层进行量化model:需要量化的 DiT 模型scale:可选的预计算缩放因子(dict 或 safetensors 文件路径)
export_quantized_weight(model, save_path):导出量化权重及缩放因子model:已量化的模型save_path:保存目录,将导出模型权重和fp8_scales.safetensors文件
启动量化流程#
方式1:使用命令行工具#
使用 scripts/diffusion/run_diffusion.py 脚本进行量化与推理:
# 在线量化并运行推理
python scripts/diffusion/run_diffusion.py \
--model-name-or-path black-forest-labs/FLUX.1-schnell \
--quant-type fp8-per-tensor \
--prompt "A cat holding a sign that says hello world" \
--height 1024 --width 1024 --steps 4 --guidance 0.0 --seed 0
# 量化模型并导出量化权重
python scripts/diffusion/run_diffusion.py \
--model-name-or-path black-forest-labs/FLUX.1-schnell \
--fp8-model-save-path /path/to/save/quantized_model \
--quant-type fp8-per-tensor
# 加载已量化模型并运行推理
python scripts/diffusion/run_diffusion.py \
--model-name-or-path black-forest-labs/FLUX.1-schnell \
--fp8-model-load-path /path/to/quantized_model \
--quant-type fp8-per-tensor \
--prompt "A cat holding a sign that says hello world" \
--height 1024 --width 1024 --steps 4 --guidance 0.0 --seed 0
方式2:使用 Python API#
从零开始量化#
import torch
from diffusers import FluxPipeline
from angelslim.compressor.diffusion import DynamicDiTQuantizer
pipe = FluxPipeline.from_pretrained("black-forest-labs/FLUX.1-schnell", torch_dtype=torch.bfloat16)
quantizer = DynamicDiTQuantizer(quant_type="fp8-per-tensor")
quantizer.convert_linear(pipe.transformer)
pipe.to("cuda")
image = pipe(
"A cat holding a sign that says hello world",
height=1024, width=1024,
guidance_scale=0.0, num_inference_steps=4, max_sequence_length=256,
generator=torch.Generator("cuda").manual_seed(0)
).images[0]
image.save("flux-schnell_fp8_per_tensor.png")
加载预量化模型和缩放因子#
import torch
from diffusers import FluxPipeline, FluxTransformer2DModel
from angelslim.compressor.diffusion import DynamicDiTQuantizer
from safetensors.torch import load_file
# 加载量化后的transformer和缩放因子
dit = FluxTransformer2DModel.from_pretrained("/path/to/quantized_model/")
pipe = FluxPipeline.from_pretrained("black-forest-labs/FLUX.1-schnell", transformer=dit, torch_dtype=torch.bfloat16)
scale = load_file("/path/to/quantized_model/fp8_scales.safetensors")
# 使用缩放因子进行量化
quantizer = DynamicDiTQuantizer(quant_type="fp8-per-tensor")
quantizer.convert_linear(pipe.transformer, scale=scale)
pipe.to("cuda")
# 推理示例
image = pipe(
"A cat holding a sign that says hello world",
height=1024, width=1024,
guidance_scale=0.0, num_inference_steps=4, max_sequence_length=256,
generator=torch.Generator("cuda").manual_seed(0)
).images[0]
image.save("flux-schnell_fp8_per_tensor.png")
灵活的层选择#
支持通过 include/exclude 模式灵活筛选需要量化的层:
from angelslim.compressor.diffusion import DynamicDiTQuantizer
# 字符串匹配
quantizer = DynamicDiTQuantizer(
quant_type="fp8-per-tensor",
include_patterns=["linear", "attention"],
exclude_patterns=["embed", "norm"]
)
# 正则表达式匹配
quantizer = DynamicDiTQuantizer(
quant_type="fp8-per-tensor",
include_patterns=[r".*\.linear\d+", r".*\.attn.*"],
exclude_patterns=[r".*embed.*"]
)
# 字符串和正则混合使用
quantizer = DynamicDiTQuantizer(
quant_type="fp8-per-tensor",
include_patterns=["linear", r".*\.attn.*"],
exclude_patterns=["embed", r".*norm.*"]
)
部署#
量化后的模型可直接用于推理。如需导出量化权重以便后续复用,可使用以下方法:
import torch
from diffusers import FluxPipeline
from angelslim.compressor.diffusion import DynamicDiTQuantizer
pipe = FluxPipeline.from_pretrained("black-forest-labs/FLUX.1-schnell", torch_dtype=torch.bfloat16)
quantizer = DynamicDiTQuantizer(quant_type="fp8-per-tensor")
# 导出量化权重和缩放因子
quantizer.export_quantized_weight(pipe.transformer, save_path="/path/to/save/quantized_model/")
导出的模型目录将包含:
量化后的模型权重文件
fp8_scales.safetensors:FP8 缩放因子文件
导出后可通过上述”加载预量化模型和缩放因子”的方式加载使用。