# Précision et compilation

La basse précision et la compilation sont deux façons d’accélérer l’inférence de Diffusers. Chargez les poids en `bfloat16` ou `float16`, puis compilez le débruiteur (le UNet ou le transformer) avec `torch.compile` ou une compilation régionale.

## Type de données du modèle

La précision et le type de données des poids du modèle influencent la vitesse d’inférence, car une précision plus élevée nécessite plus de mémoire pour le chargement et plus de temps pour effectuer les calculs. Diffusers charge les poids du modèle en `float32` lorsque vous omettez `dtype`, ce qui fait du changement de type de données une méthode simple pour accélérer rapidement l’inférence.

`bfloat16` est similaire à `float16` mais il est plus robuste aux erreurs numériques. La prise en charge matérielle de `bfloat16` varie, mais la plupart des GPU modernes sont capables de prendre en charge `bfloat16`.

```py
import torch
from diffusers import StableDiffusionXLPipeline

pipeline = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.bfloat16
).to("cuda")  # or "mps", "xpu", "cpu"

prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
pipeline(prompt, num_inference_steps=30).images[0]
```

`float16` est similaire à `bfloat16` mais peut être plus sujet aux erreurs numériques.

```py
import torch
from diffusers import StableDiffusionXLPipeline

pipeline = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"

prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
pipeline(prompt, num_inference_steps=30).images[0]
```

Le mode [TensorFloat-32](https://blogs.nvidia.com/blog/2020/05/14/tensorfloat-32-precision-format/) (`tf32`) est pris en charge sur les GPU NVIDIA Ampere et plus récents. Il exécute les opérations de convolution et de multiplication de matrices en `tf32`. Le stockage et les autres opérations restent en `float32`. Ce mode accélère les opérations exécutées en `float32`, ce qui est donc particulièrement utile lorsque le pipeline, ou une partie de celui-ci, reste en `float32`.

PyTorch n’active le mode `tf32` par défaut que pour les convolutions et il faut l’activer explicitement pour les multiplications de matrices.

```py
import torch
from diffusers import StableDiffusionXLPipeline

torch.backends.cuda.matmul.allow_tf32 = True

pipeline = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.float32
).to("cuda")  # or "mps", "xpu", "cpu"

prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
pipeline(prompt, num_inference_steps=30).images[0]
```

Consultez la documentation sur l'[entraînement en précision mixte](https://huggingface.co/docs/transformers/en/perf_train_gpu_one#mixed-precision) pour plus de détails.

## Attention par produit scalaire

[L'attention par produit scalaire mis à l'échelle (SDPA)](https://pytorch.org/docs/stable/generated/torch.nn.functional.scaled_dot_product_attention.html) est l'attention par défaut sur PyTorch 2.0 et versions ultérieures, via `AttnProcessor2_0` ou le backend `native` du dispatcheur d'attention. PyTorch sélectionne un noyau SDPA adapté à votre matériel. Pour FlashAttention, SageAttention, xFormers, les noyaux Hub et d'autres backends, consultez [Backends d'attention](./attention_backends).

## torch.compile

[torch.compile](https://pytorch.org/tutorials/intermediate/torch_compile_tutorial.html) accélère l’inférence en compilant le code et les opérations PyTorch en noyaux optimisés. Vous compilez généralement le débruiteur, qui domine le temps d’exécution, à savoir `pipeline.unet` ou `pipeline.transformer`, et parfois le VAE également.

Activez les paramètres de compilateur suivants pour une vitesse maximale (reportez-vous à la [liste complète](https://github.com/pytorch/pytorch/blob/main/torch/_inductor/config.py) pour plus d'options).

```py
import torch
from diffusers import StableDiffusionXLPipeline

torch._inductor.config.conv_1x1_as_mm = True
torch._inductor.config.coordinate_descent_tuning = True
torch._inductor.config.epilogue_fusion = False
torch._inductor.config.coordinate_descent_check_all_directions = True
```

Chargez et compilez le débruiteur et le VAE. Utilisez `pipeline.unet` sur les pipelines UNet tels que Stable Diffusion XL, ou `pipeline.transformer` sur les pipelines de type Flux et DiT. Plusieurs modes différents sont disponibles, mais `"max-autotune"` recherche les noyaux les plus rapides et utilise les graphes CUDA. Les graphes CUDA réduisent la surcharge en lançant plusieurs opérations GPU via une seule opération CPU.

Changer la disposition de la mémoire en [channels_last](./memory#torchchannelslast) peut également accélérer les modèles intensifs en convolution, comme les UNets et les VAEs. Effectuez d’abord un benchmark, car certains modèles s’exécutent plus lentement.

```py
pipeline = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.unet.to(memory_format=torch.channels_last)
pipeline.unet = torch.compile(
    pipeline.unet, mode="max-autotune", fullgraph=True
)
pipeline.vae.to(memory_format=torch.channels_last)
pipeline.vae.decode = torch.compile(
    pipeline.vae.decode,
    mode="max-autotune",
    fullgraph=True
)

prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
pipeline(prompt, num_inference_steps=30).images[0]
```

La compilation est lente lors de la première exécution, en particulier avec `"max-autotune"`, car le compilateur recherche les noyaux et réutilise ensuite le même objet de pipeline compilé (voir [Compile Time Caching](https://docs.pytorch.org/tutorials/recipes/torch_compile_caching_tutorial.html) et [Caching Configuration](https://docs.pytorch.org/tutorials/recipes/torch_compile_caching_configuration_tutorial.html) pour savoir comment configurer le comportement de mise en cache). Appeler le pipeline compilé avec une taille d'image différente déclenche une recompilation.

### Compilation de formes dynamiques

`torch.compile` suit les formes des entrées et les conditions, et si celles-ci diffèrent, il recompile le modèle. Par exemple, si un modèle est compilé sur une image de résolution 1024x1024 puis utilisé sur une image de résolution différente, cela déclenche une recompilation.

Pour éviter la recompilation, ajoutez `dynamic=True` afin de générer un noyau plus dynamique et d'éviter ainsi la recompilation lorsque les conditions changent.

```diff
+ torch.fx.experimental._config.use_duck_shape = False
+ pipeline.unet = torch.compile(
    pipeline.unet, fullgraph=True, dynamic=True
)
```

Spécifier `use_duck_shape=False` indique au compilateur s'il doit utiliser la même variable symbolique pour représenter les tailles d'entrée identiques. Pour plus de détails, consultez ce [commentaire](https://github.com/huggingface/diffusers/pull/11327#discussion_r2047659790).

Tous les modèles ne bénéficient pas nécessairement de la compilation dynamique dès l’origine et peuvent nécessiter des modifications. Consultez cette [PR](https://github.com/huggingface/diffusers/pull/11297/) qui a amélioré l’implémentation de [AuraFlowPipeline](/docs/diffusers/main/fr/api/pipelines/aura_flow#diffusers.AuraFlowPipeline) afin de tirer parti de la compilation dynamique.

N'hésitez pas à ouvrir un ticket si la compilation dynamique ne fonctionne pas comme prévu pour un modèle Diffusers.

### Compilation régionale

[La compilation régionale](https://docs.pytorch.org/tutorials/recipes/regional_compilation.html) réduit la latence de démarrage à froid en ne compilant que les *blocs petits et fréquemment répétés* d'un modèle - généralement une couche de transformer - et permet de réutiliser les artefacts compilés pour chaque occurrence ultérieure. Pour de nombreuses architectures de diffusion, cela offre des accélérations d'exécution comparables à celles de la compilation du graphe complet et peut réduire le temps de compilation jusqu'à 8 à 10 fois.

Utilisez la méthode [compile_repeated_blocks()](/docs/diffusers/main/fr/api/models/overview#diffusers.ModelMixin.compile_repeated_blocks), un utilitaire qui encapsule `torch.compile`, sur le débruiteur. Appelez-la sur `pipeline.unet` ou `pipeline.transformer`, selon le pipeline.

```py
import torch
from diffusers import StableDiffusionXLPipeline

pipeline = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    dtype=torch.float16,
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.unet.compile_repeated_blocks(fullgraph=True)
```

Pour activer la compilation régionale pour un nouveau modèle, définissez `_repeated_blocks` avec les noms de classes des blocs répétés (chaînes de caractères). Pour le UNet de SDXL, utilisez `BasicTransformerBlock`. Les débruiteurs Transformer listent de la même manière les noms de classes de leurs blocs répétés.

```py
_repeated_blocks = ["BasicTransformerBlock"]
```

Il existe également une méthode [compile_regions](https://github.com/huggingface/accelerate/blob/273799c85d849a1954a4f2e65767216eb37fa089/src/accelerate/utils/other.py#L78) dans [Accelerate](https://huggingface.co/docs/accelerate/index) qui sélectionne automatiquement les blocs candidats d'un modèle à compiler. Le reste du graphe est compilé séparément. C'est utile pour des expériences rapides, car il y a moins d'options pour définir quels blocs compiler ou ajuster les drapeaux de compilation.

```bash
pip install -U accelerate
```

```py
import torch
from diffusers import StableDiffusionXLPipeline
from accelerate.utils import compile_regions

pipeline = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.unet = compile_regions(pipeline.unet, mode="reduce-overhead", fullgraph=True)
```

[compile_repeated_blocks()](/docs/diffusers/main/fr/api/models/overview#diffusers.ModelMixin.compile_repeated_blocks) est volontairement explicite. Énumérez les blocs à répéter dans `_repeated_blocks` et l’assistant ne compile que ces blocs. Il offre un comportement prévisible et un raisonnement simple sur la réutilisation du cache en une seule ligne de code.

### Interruptions de graphe

Définissez `fullgraph=True` afin que torch.compile lève une erreur en cas de rupture de graphe au lieu de scinder silencieusement le graphe, ce qui réduit l’accélération.

### Synchronisation GPU

Après chaque prédiction du débruiteur, le pipeline appelle la méthode `step` du planificateur, qui indexe `sigmas`. Laisser `sigmas` sur le GPU peut forcer une synchronisation CPU↔GPU à chaque étape. Ce coût est facile à manquer tant que le débruiteur n'est pas compilé. Il est préférable de laisser `sigmas` sur le CPU (les planificateurs Diffusers tels que Euler le font déjà).

### Benchmarks

Consultez le jeu de données [diffusers/benchmarks](https://huggingface.co/datasets/diffusers/benchmarks) pour consulter les données de latence d'inférence et d'utilisation de la mémoire des pipelines compilés.

Le dépôt [diffusers-torchao](https://github.com/sayakpaul/diffusers-torchao#benchmarking-results) contient également des résultats de benchmark pour les versions compilées de Flux et CogVideoX.

## Kernels

[Kernels](https://huggingface.co/docs/kernels/index) est une bibliothèque pour construire, distribuer et charger des noyaux de calcul optimisés sur le [Hub](https://huggingface.co/kernels-community). Elle prend en charge les noyaux [attention](./attention_backends#set-a-backend-on-the-model) et les noyaux CUDA personnalisés pour des opérations telles que RMSNorm, GEGLU, RoPE et AdaLN.

Le guide [Diffusers Pipeline Integration](https://github.com/huggingface/kernels/blob/main/kernel-builder/skills/cuda-kernels/references/diffusers-integration.md) montre comment intégrer un noyau avec la compétence [add cuda-kernels](https://github.com/huggingface/kernels/blob/main/kernel-builder/skills/cuda-kernels/SKILL.md). Cette compétence permet à un agent, comme Claude ou Codex, d'écrire des noyaux personnalisés ciblant un modèle spécifique et votre matériel. L'article [Custom kernels for all from Codex and Claude](https://huggingface.co/blog/custom-cuda-kernels-agent-skills) fournit plus de détails.

Par exemple, un noyau RMSNorm personnalisé (généré par la compétence `add cuda-kernels`) avec [torch.compile](#torchcompile) accélère la génération de LTX-Video de 1,43 fois sur une H100.

<iframe src="https://huggingface.co/datasets/docs-benchmarks/kernel-ltx-video/embed/viewer/default/train" frameborder="0" width="100%" height="560px"
>

## Quantification dynamique

La quantification dynamique des activations en int8 est disponible dans [torchao](../quantization/torchao). Utilisez [TorchAoConfig](/docs/diffusers/main/fr/api/quantization#diffusers.TorchAoConfig) avec une configuration telle que [`Int8DynamicActivationInt8WeightConfig`](https://docs.pytorch.org/ao/stable/api_reference/generated/torchao.quantization.Int8DynamicActivationInt8WeightConfig.html), ou l'API `quantize_` de torchao. N'utilisez pas l'ancien utilitaire `apply_dynamic_quant`.

## Matrices de projection fusionnées

> [!WARNING]
> `~DiffusionPipeline.fuse_qkv_projections` est expérimental.

Une entrée est projetée dans trois sous-espaces, représentés par les matrices de projection Q, K et V, au sein d'un bloc d'attention. Ces projections sont généralement calculées séparément, mais vous pouvez les combiner horizontalement en une seule matrice et effectuer la projection en une seule étape. Cela augmente la taille des multiplications de matrices des projections d'entrée et améliore également l'impact de la quantification.

```py
pipeline.fuse_qkv_projections()
```

## Étapes suivantes

- Lisez le billet de blog [Presenting Flux Fast: Making Flux go brrr on H100s](https://pytorch.org/blog/presenting-flux-fast-making-flux-go-brrr-on-h100s/) pour en savoir plus sur la manière de combiner toutes ces optimisations avec [TorchInductor](https://docs.pytorch.org/docs/stable/torch.compiler.html) et [AOTInductor](https://docs.pytorch.org/docs/stable/torch.compiler_aot_inductor.html) afin d’obtenir un gain de vitesse d’environ 2,5x en utilisant les recettes de [flux-fast](https://github.com/huggingface/flux-fast).

    Ces recettes prennent en charge le matériel AMD et [Flux.1 Kontext Dev](https://huggingface.co/black-forest-labs/FLUX.1-Kontext-dev).

- Consultez le billet de blog [torch.compile and Diffusers: A Hands-On Guide to Peak Performance](https://pytorch.org/blog/torch-compile-and-diffusers-a-hands-on-guide-to-peak-performance/) pour maximiser les performances avec `torch.compile` pour les modèles de diffusion.

