Buckets:
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.
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.
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 (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.
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 pour plus de détails.
Attention par produit scalaire
L'attention par produit scalaire mis à l'échelle (SDPA) 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.
torch.compile
torch.compile 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 pour plus d'options).
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 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.
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 et Caching Configuration 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.
+ 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.
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 qui a amélioré l’implémentation de 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 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(), un utilitaire qui encapsule torch.compile, sur le débruiteur. Appelez-la sur pipeline.unet ou pipeline.transformer, selon le pipeline.
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.
_repeated_blocks = ["BasicTransformerBlock"]
Il existe également une méthode compile_regions dans Accelerate 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.
pip install -U accelerate
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() 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 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 contient également des résultats de benchmark pour les versions compilées de Flux et CogVideoX.
Kernels
Kernels est une bibliothèque pour construire, distribuer et charger des noyaux de calcul optimisés sur le Hub. Elle prend en charge les noyaux attention et les noyaux CUDA personnalisés pour des opérations telles que RMSNorm, GEGLU, RoPE et AdaLN.
Le guide Diffusers Pipeline Integration montre comment intégrer un noyau avec la compétence add cuda-kernels. 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 fournit plus de détails.
Par exemple, un noyau RMSNorm personnalisé (généré par la compétence add cuda-kernels) avec torch.compile accélère la génération de LTX-Video de 1,43 fois sur une H100.
Xet Storage Details
- Size:
- 15.1 kB
- Xet hash:
- 319e420e48a86b087b3c3f7e3d5322076dd5a45246f06337272ab97225f6135c
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.