# SDNQ

[SDNQ](https://github.com/Disty0/sdnq) (SD.Next Quantization) là một backend lượng tử hóa không cần huấn luyện, hỗ trợ nhiều loại dtype trọng số (từ int8 xuống 2-bit, FP8 và các định dạng float bit thấp khác) với tùy chọn hiệu chỉnh SVD, xoay Hadamard và matmul INT8/FP8 đã lượng tử hóa để suy luận nhanh hơn. Nó chạy trên CUDA, ROCm, XPU, MPS và CPU.

Cài đặt thư viện `sdnq` để sử dụng backend này.

```bash
pip install sdnq
```

## Tải checkpoint đã lượng tử hóa

Cấu hình lượng tử hóa của một checkpoint SDNQ đã được lượng tử hóa trước được lưu trong `config.json` của nó, do đó nó được nạp giống như bất kỳ model nào khác, không cần tham số `quantization_config`. Yêu cầu duy nhất là đã cài đặt `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]
> Đặt `DIFFUSERS_SDNQ_TRANSFORMERS=1` (trước khi import Diffusers) khi bạn tải một mô hình Transformers đã được lượng tử hóa SDNQ một cách độc lập, chẳng hạn như một text encoder đã lượng tử hóa hoặc một thành phần LLM độc lập trong một pipeline mô-đun. Biến này cho phép `sdnq` tự đăng ký với Transformers để mô hình đã lượng tử hóa được tải đúng cách. Bạn không cần đặt biến này khi một transformer diffusers đã lượng tử hóa SDNQ được tải cùng với nó, vì việc tải transformer đó đã import `sdnq` và đăng ký nó. Biến này tắt mặc định để các pipeline không sử dụng SDNQ không bao giờ import `sdnq`.

## Lượng tử hóa một mô hình ngay khi chạy

Truyền [SDNQConfig](/docs/diffusers/v0.43.0/vi/api/quantization#diffusers.SDNQConfig) vào `from_pretrained` để lượng tử hóa mô hình trong quá trình tải. Sử dụng [PipelineQuantizationConfig](/docs/diffusers/v0.43.0/vi/api/quantization#diffusers.PipelineQuantizationConfig) để lượng tử hóa các thành phần cụ thể của pipeline.

```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"
```

Hoặc lượng tử hóa trực tiếp một thành phần mô hình đơn lẻ.

```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,
)
```

Tất cả các đối số được chuyển tiếp đến [`sdnq.SDNQConfig`](https://github.com/Disty0/sdnq). Tham khảo tài liệu SDNQ để biết danh sách đầy đủ các dtype và tùy chọn được hỗ trợ.

## Chọn các lớp cần lượng tử hóa

Một số lớp nhạy cảm với lượng tử hóa hơn các lớp khác, và việc bỏ qua các lớp nhạy cảm này giúp cải thiện chất lượng với chi phí bộ nhớ rất nhỏ. SDNQ xử lý điều này ngay từ đầu: nó đi kèm các danh sách bỏ qua tích hợp sẵn (một danh sách chung cùng các danh sách riêng cho từng mô hình của nhiều kiến trúc) được áp dụng tự động, do đó các lớp nhạy cảm thông thường sẽ không bị lượng tử hóa mà không cần cấu hình. Để kiểm soát chi tiết hơn, nó cũng có thể chọn lớp động, đo lỗi lượng tử hóa của từng lớp và bỏ qua những lớp vượt quá ngưỡng tổn thất. Xem [hướng dẫn lượng tử hóa động SDNQ](https://github.com/vladmandic/sdnext/wiki/SDNQ-Quantization#dynamic-loss-threshold) để biết thêm chi tiết.

## Suy luận nhanh hơn với matmul lượng tử hóa

Mặc định, SDNQ khử lượng hóa (dequantize) trọng số trở lại kiểu dữ liệu tính toán (compute dtype) trước mỗi phép nhân ma trận (matmul). Việc bật tính năng matmul lượng hóa (quantized matmul) sẽ thực hiện phép nhân ma trận trực tiếp trong kiểu dữ liệu độ chính xác thấp (INT8/FP8/FP16), giúp nhanh hơn trên phần cứng có cài đặt [Triton](https://github.com/triton-lang/triton) hoạt động (CUDA, ROCm, hoặc XPU).

Bật tính năng này trên một model đã được nạp bằng `apply_sdnq_options_to_model`, hàm này sẽ đọc cấu hình lượng tử hóa hiện có của model và áp dụng lại tùy chọn tại chỗ. Cách này cũng hoạt động với các checkpoint đã được lượng tử hóa trước, nơi không có `SDNQConfig` nào được truyền vào.

```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

Các mô hình lượng tử hóa SDNQ tương thích với [torch.compile](../optimization/fp16#torchcompile) để tăng tốc độ thêm, bao gồm cả khi kết hợp với [group offloading](../optimization/memory#group-offloading).

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

## Lưu một mô hình đã lượng tử hóa

Các mô hình đã lượng tử hóa có thể được xuất ra bằng `save_pretrained` và tải lại mà không cần `quantization_config`.

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

## Tài nguyên

- [kho SDNQ](https://github.com/Disty0/sdnq)
- [Các mô hình SDNQ đã lượng hóa trước trên Hub](https://huggingface.co/models?search=sdnq)

