Spaces:
Running on Zero
Running on Zero
| """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]()) | |