# SDNQ

[SDNQ](https://github.com/Disty0/sdnq)（SD.Next Quantization）是一个无需训练的量化后端，支持多种权重数据类型（从 int8 到 2-bit，以及 FP8 和其他低比特浮点格式），并可选支持 SVD 校正、Hadamard 旋转以及用于加速推理的量化 INT8/FP8 矩阵乘法。它可在 CUDA、ROCm、XPU、MPS 和 CPU 上运行。

安装 `sdnq` 库以使用此后端。

```bash
pip install sdnq
```

## 加载预量化检查点

预量化 SDNQ 检查点的量化配置存储在其 `config.json` 中，因此可以像加载其他模型一样直接加载，无需提供 `quantization_config` 参数。唯一的条件是已安装 `sdnq`。

```python
import torch
from diffusers import DiffusionPipeline

pipe = DiffusionPipeline.from_pretrained(
    "Disty0/Z-Image-Turbo-SDNQ-uint4-svd-r32",
    dtype=torch.bfloat16,
).to("cuda")  # or "mps", "xpu", "cpu"

image = pipe("a cat holding a sign that says hello").images[0]
image.save("output.png")
```

> [!TIP]
> 在单独加载 SDNQ 量化的 Transformers 模型（例如量化的文本编码器，或模块化流水线中独立的 LLM 组件）时，请在导入 Diffusers 之前设置 `DIFFUSERS_SDNQ_TRANSFORMERS=1`。该设置可让 `sdnq` 向 Transformers 注册自身，从而确保量化模型能够正确加载。如果同时加载了 SDNQ 量化的 diffusers transformer，则无需此设置，因为加载该 transformer 时已经导入了 `sdnq` 并完成了注册。该设置默认关闭，因此不使用 SDNQ 的流水线不会导入 `sdnq`。

## 在运行时量化模型

将 [SDNQConfig](/docs/diffusers/v0.43.0/zh/api/quantization#diffusers.SDNQConfig) 传递给 `from_pretrained` 可在加载模型时对其进行量化。使用 [PipelineQuantizationConfig](/docs/diffusers/v0.43.0/zh/api/quantization#diffusers.PipelineQuantizationConfig) 可量化特定的流水线组件。

```python
import torch
from diffusers import DiffusionPipeline, PipelineQuantizationConfig, SDNQConfig

pipeline_quant_config = PipelineQuantizationConfig(
    quant_mapping={"transformer": SDNQConfig(weights_dtype="uint4", use_svd=True)}
)
pipe = DiffusionPipeline.from_pretrained(
    "Tongyi-MAI/Z-Image-Turbo",
    quantization_config=pipeline_quant_config,
    dtype=torch.bfloat16,
).to("cuda")  # or "mps", "xpu", "cpu"
```

或者直接量化单个模型组件。

```python
import torch
from diffusers import ZImageTransformer2DModel, SDNQConfig

transformer = ZImageTransformer2DModel.from_pretrained(
    "Tongyi-MAI/Z-Image-Turbo",
    subfolder="transformer",
    quantization_config=SDNQConfig(weights_dtype="int8"),
    dtype=torch.bfloat16,
)
```

所有参数都会转发给 [`sdnq.SDNQConfig`](https://github.com/Disty0/sdnq)。有关支持的 dtype 和选项的完整列表，请参阅 SDNQ 文档。

## 选择要量化的层

某些层比其他层对量化更敏感，跳过这些敏感层可以在几乎不增加内存开销的情况下提升质量。SDNQ 开箱即用：它内置了跳过列表（一个通用列表，以及针对许多架构的逐模型列表），并会自动应用这些列表，因此通常敏感的层无需任何配置即可保持未量化状态。为了进行更精细的控制，它还可以动态选择层，通过测量每层的量化误差并跳过超过损失阈值的层来实现。有关详细信息，请参阅 [SDNQ 动态量化指南](https://github.com/vladmandic/sdnext/wiki/SDNQ-Quantization#dynamic-loss-threshold)。

## 使用量化矩阵乘法实现更快的推理

默认情况下，SDNQ 会在每次矩阵乘法之前将权重反量化回计算数据类型。启用量化矩阵乘法后，矩阵乘法将直接在低精度数据类型（INT8/FP8/FP16）下执行，这在具备可用 [Triton](https://github.com/triton-lang/triton) 安装环境（CUDA、ROCm 或 XPU）的硬件上速度更快。

在已加载的模型上，使用 `apply_sdnq_options_to_model` 启用该功能。它会读取模型现有的量化配置，并就地重新应用该选项。对于预量化检查点同样适用，此时无需传入 `SDNQConfig`。

```python
import torch
from diffusers import DiffusionPipeline
from sdnq.common import use_torch_compile as triton_is_available
from sdnq.loader import apply_sdnq_options_to_model

pipe = DiffusionPipeline.from_pretrained(
    "Disty0/Z-Image-Turbo-SDNQ-uint4-svd-r32",
    dtype=torch.bfloat16,
).to("cuda")  # or "mps", "xpu", "cpu"

if triton_is_available and (torch.cuda.is_available() or torch.xpu.is_available()):
    pipe.transformer = apply_sdnq_options_to_model(pipe.transformer, use_quantized_matmul=True)
    pipe.text_encoder = apply_sdnq_options_to_model(pipe.text_encoder, use_quantized_matmul=True)
```

## torch.compile

SDNQ 量化模型与 [torch.compile](../optimization/fp16#torchcompile) 兼容，可进一步提升速度，包括与 [group offloading](../optimization/memory#group-offloading) 配合使用。

```python
transformer.compile(fullgraph=True)
```

## 保存量化模型

量化模型可以通过 `save_pretrained` 进行序列化，并在重新加载时无需提供 `quantization_config`。

```python
transformer.save_pretrained("z-image-turbo-sdnq-int8")
```

## 资源

- [SDNQ 仓库](https://github.com/Disty0/sdnq)
- [Hub 上的预量化 SDNQ 模型](https://huggingface.co/models?search=sdnq)

