diffu_test / diffu /quantize.py
Gabriel's picture
Diffu Studio ZeroGPU Space: app.py + vendored packages + aokit AoT + redesigned panel
333ff0e verified
Raw
History Blame Contribute Delete
2.92 kB
"""Post-training weight quantization of the SD3 backbone for faster inference (torchao).
Weight-only quantization of the MMDiT transformer's Linear layers — the bulk of inference compute
(``sample_steps`` denoise iterations × CFG). The frozen VAE + style encoder run O(1) per generation,
so they stay bf16. Quantization is POST-TRAINING and INFERENCE-ONLY — it never touches training.
The speedup comes from compiled low-bit matmul kernels, so quantize BEFORE ``Backbone.compile_blocks``
(torchao + ``torch.compile`` is the supported combo; int8 in eager dequantizes and can be SLOWER).
bf16 is the accuracy baseline; int8/fp8 trade a little precision for speed/memory on memory-bound
GEMMs — always validate gen_CER before shipping (``scripts/bench_quant.py``).
"""
from __future__ import annotations
from typing import Literal
import torch
QuantMode = Literal["int8", "int8dq", "fp8", "fp8dq"]
def quantize_backbone(model: torch.nn.Module, mode: QuantMode = "int8") -> None:
"""In-place torchao weight quantization of ``model.backbone.transformer`` Linear layers.
Args:
model: a built ``Diffu`` (needs ``.backbone.transformer``).
mode: ``int8`` = int8 weight-only; ``int8dq`` = int8 dynamic-activation + int8 weight;
``fp8`` = float8 weight-only; ``fp8dq`` = float8 dynamic-activation + float8 weight
(full fp8 GEMM — best on Blackwell's fp8 tensor cores). fp8 modes need CC ≥ 8.9.
Raises:
ValueError: unknown ``mode``.
RuntimeError: an fp8 mode requested on pre-Ada hardware.
"""
from torchao.quantization import ( # torchao 0.17 config-based API
Float8DynamicActivationFloat8WeightConfig,
Float8WeightOnlyConfig,
Int8DynamicActivationInt8WeightConfig,
Int8WeightOnlyConfig,
quantize_,
)
# int8 version=2: the maintained Int8Tensor path (torchao 0.17 deprecates the v1 default's legacy
# AffineQuantizedTensor route). set_inductor_config=False everywhere: the default True flips GLOBAL
# inductor flags + TF32 at quantize time, which makes any quant-vs-baseline benchmark
# apples-to-oranges — callers own their global compile settings.
recipes = {
"int8": lambda: Int8WeightOnlyConfig(version=2, set_inductor_config=False),
"int8dq": lambda: Int8DynamicActivationInt8WeightConfig(version=2, set_inductor_config=False),
"fp8": lambda: Float8WeightOnlyConfig(set_inductor_config=False),
"fp8dq": lambda: Float8DynamicActivationFloat8WeightConfig(set_inductor_config=False),
}
if mode not in recipes:
raise ValueError(f"unknown quant mode {mode!r}; choose from {sorted(recipes)}")
if mode.startswith("fp8") and torch.cuda.get_device_capability() < (8, 9):
raise RuntimeError("fp8 needs compute capability >= 8.9 (Ada/Hopper/Blackwell)")
quantize_(model.backbone.transformer, recipes[mode]())