# SDNQ

[SDNQ](https://github.com/Disty0/sdnq) (SD.Next Quantization) est un backend de quantification sans entraînement qui prend en charge une large gamme de dtypes de poids (de int8 jusqu’au 2 bits, FP8 et d’autres formats flottants à faible nombre de bits), avec correction SVD, rotation de Hadamard et matmul INT8/FP8 quantifiés en option pour une inférence plus rapide. Il fonctionne sur CUDA, ROCm, XPU, MPS et CPU.

Installez la bibliothèque `sdnq` pour utiliser ce backend.

```bash
pip install sdnq
```

## Charger un point de contrôle pré-quantifié

La configuration de quantisation d'un point de contrôle SDNQ pré-quantisé est stockée dans son `config.json`, il se charge donc comme n'importe quel autre modèle, sans avoir besoin de l'argument `quantization_config`. La seule exigence est d'avoir `sdnq` installé.

```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]
> Définissez `DIFFUSERS_SDNQ_TRANSFORMERS=1` (avant d’importer Diffusers) lorsque vous chargez un modèle Transformers quantisé SDNQ de manière isolée, par exemple un encodeur de texte quantisé ou un composant LLM autonome dans un pipeline modulaire. Cela permet à `sdnq` de s’enregistrer auprès de Transformers afin que le modèle quantisé soit chargé correctement. Vous n’en avez pas besoin lorsqu’un transformer diffusers quantisé SDNQ est chargé en même temps, car le chargement de ce transformer importe déjà `sdnq` et l’enregistre. Cette option est désactivée par défaut afin que les pipelines n’utilisant pas SDNQ n’importent jamais `sdnq`.

## Quantifier un modèle à la volée

Passez un [SDNQConfig](/docs/diffusers/v0.43.0/fr/api/quantization#diffusers.SDNQConfig) à `from_pretrained` pour quantifier un modèle lors de son chargement. Utilisez [PipelineQuantizationConfig](/docs/diffusers/v0.43.0/fr/api/quantization#diffusers.PipelineQuantizationConfig) pour quantifier des composants spécifiques du 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"
```

Ou quantifiez directement un composant unique du modèle.

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

Tous les arguments sont transmis à [`sdnq.SDNQConfig`](https://github.com/Disty0/sdnq). Reportez-vous à la documentation de SDNQ pour la liste complète des dtypes et options pris en charge.

## Choisir les couches à quantiser

Certain couches sont plus sensibles à la quantification que d'autres, et l'exclusion des couches sensibles améliore la qualité à un coût mémoire négligeable. SDNQ gère cela nativement : il fournit des listes d'exclusion intégrées (une liste générique ainsi que des listes par modèle pour de nombreuses architectures) qui sont appliquées automatiquement, de sorte que les couches sensibles habituelles restent non quantifiées sans aucune configuration. Pour un contrôle plus fin, il peut également sélectionner dynamiquement les couches en mesurant l'erreur de quantification par couche et en excluant celles qui dépassent un seuil de perte. Consultez le [guide de quantification dynamique SDNQ](https://github.com/vladmandic/sdnext/wiki/SDNQ-Quantization#dynamic-loss-threshold) pour plus de détails.

## Inférence plus rapide avec des produits matriciels quantifiés

Par défaut, SDNQ déquantise les poids vers le type de calcul avant chaque matmul. L’activation du matmul quantifié exécute à la place le matmul directement dans un type de précision réduite (INT8/FP8/FP16), ce qui est plus rapide sur le matériel disposant d’une installation [Triton](https://github.com/triton-lang/triton) fonctionnelle (CUDA, ROCm ou XPU).

Activez-le sur un modèle chargé à l’aide de `apply_sdnq_options_to_model`, qui lit la configuration de quantification existante du modèle et réapplique l’option sur place. Cela fonctionne également pour les points de contrôle pré-quantifiés, où aucune `SDNQConfig` n’est transmise.

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

Les modèles quantifiés SDNQ sont compatibles avec [torch.compile](../optimization/fp16#torchcompile) pour des accélérations supplémentaires, y compris en combinaison avec le [group offloading](../optimization/memory#group-offloading).

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

## Enregistrer un modèle quantifié

Les modèles quantifiés peuvent être sérialisés avec `save_pretrained` et rechargés sans `quantization_config`.

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

## Ressources

- [Dépôt SDNQ](https://github.com/Disty0/sdnq)
- [Modèles SDNQ préquantifiés sur le Hub](https://huggingface.co/models?search=sdnq)

