L'Attention
dans ComfyUI
Pourquoi un prompt de dix mots peut sculpter chaque recoin d'une image ? Pourquoi passer de 512 à 1024 px multiplie la VRAM par 16 ? Pourquoi Flash Attention est plus rapide sans changer le résultat ? Tout vient d'un seul mécanisme mathématique : l'attention.
01 // Le cerveau du modèle de diffusion
Un modèle de diffusion ne "dessine" pas. Il part d'une image de bruit pur — une neige numérique — et enlève progressivement ce bruit, étape par étape (les "steps"), jusqu'à révéler l'image sous-jacente. À chaque étape, une question difficile : quel bruit enlever, et où ?
La réponse vient du mécanisme d'attention. C'est lui qui permet à chaque région de l'image de comprendre son contexte global — et à votre prompt de guider ce processus avec précision.
En Global Illumination, chaque surface évalue sa contribution lumineuse en examinant toutes les autres surfaces. Ce dialogue permanent, c'est exactement ce que fait l'attention entre les régions d'une image. Sans GI, le rendu est plat et faux. Sans attention, l'image générée serait incohérente — chaque pixel calculé dans l'ignorance des autres.
La grande différence avec les CNN classiques (qui travaillent avec des voisinages locaux fixes, comme un filtre de flou 3×3) : l'attention est globale. Un pixel en bas à gauche peut directement influencer un pixel en haut à droite, sans traverser des dizaines de couches intermédiaires. En une seule passe.
C'est cette globalité qui donne aux modèles de diffusion modernes leur cohérence spectaculaire — et leur appétit de mémoire tout aussi spectaculaire.
02 // Q, K, V — Les trois rôles
Le mécanisme d'attention repose sur trois composantes. Comprenez ces trois rôles et tout le reste devient transparent.
Vous préparez un plan de tournage. Chaque objet du décor se pose une question : "Quelle devrait être mon apparence ?" C'est la Requête (Q). Pour répondre, il consulte une bibliothèque de planches de références. Chaque planche a une étiquette — Clé (K) — et un contenu visuel — Valeur (V). L'objet compare sa question aux étiquettes, identifie les planches les plus pertinentes, et en extrait le contenu pour se définir.
La formule, démystifiée
La même formule en quatre verbes, sans les maths :
- Comparer — chaque question (Q) est confrontée à toutes les étiquettes disponibles (K). Résultat : un score de pertinence pour chaque paire.
- Calmer — on divise ces scores par √d pour qu'ils restent dans un intervalle raisonnable. Sans ça, certains scores exploseraient et le modèle deviendrait aveugle aux nuances.
- Choisir — softmax() transforme les scores en parts d'attention (0 à 100 %, total = 100 %). C'est là que le modèle décide à quoi il prête vraiment attention.
- Récupérer — on extrait le contenu (V) proportionnellement à ces parts. Beaucoup d'attention sur un élément = beaucoup de son contenu dans la sortie.
03 // Self-Attention — L'image face à elle-même
Dans la self-attention, Q, K, et V proviennent tous de la même source : les patches de l'image latente elle-même. Chaque région interroge toutes les autres régions pour décider de son propre état.
C'est ce mécanisme qui rend les images cohérentes globalement — l'ombre suit la même direction lumineuse dans tout le cadre, les textures maintiennent le même grain, les couleurs restent dans la même palette.
Imaginez un grading colorimétrique qui ne serait plus un filtre global appliqué mécaniquement, mais un système où chaque pixel "voit" tous les autres et ajuste sa teinte en conséquence. Le fond sombre derrière un personnage n'est plus calculé indépendamment du visage — ils se co-définissent. C'est pourquoi les modèles modernes maintiennent une cohérence de lumière et de palette que les anciens générateurs pixelisés ne pouvaient pas atteindre.
04 // Cross-Attention — Le dialogue texte ↔ image
La cross-attention est ce qui rend le prompting possible. Ici, les sources sont différentes :
- Q (Requêtes) — viennent des patches de l'image latente
- K et V (Clés, Valeurs) — viennent des tokens textuels du prompt encodé
Concrètement : chaque région de l'image demande "Quels mots de mon prompt me concernent ?" Et chaque token du prompt répond avec son information sémantique. Un patch situé dans la région "tête" du personnage va naturellement attirer plus d'attention sur les tokens "visage", "cheveux", "yeux" que sur "fond" ou "ciel".
Imaginez un système UV inversé : ce ne sont plus les UVs qui pointent vers la texture, mais chaque région du mesh (Q) qui interroge une bibliothèque de descriptions matériau (K/V) pour décider de son apparence. Le mot "rouillé" dans votre prompt n'est pas appliqué uniformément comme un calque — chaque patch décide indépendamment de son degré de "rouille" selon sa position et son contexte. C'est pourquoi des prompts précis et localisés (avec Attention Mask ou régions) donnent bien meilleur résultat que des prompts vagues.
Pourquoi l'ordre des mots compte (relativement)
Les tokens en début de prompt tendent à avoir une influence légèrement plus large — les couches initiales du réseau leur accordent plus de poids. Mais l'emplacement dans le prompt n'est pas du code positional absolu : c'est le score Q·K qui décide, pas la position dans la séquence. C'est pour cela que les prompts fonctionnent mieux quand les concepts importants sont clairs sémantiquement, pas forcément en premier.
Comment le modèle choisit "qui va où" — l'exemple de la voiture
Considérons le prompt "une voiture sur une route de montagne, plan large cinématique". La question naturelle est : comment le modèle décide que tels pixels représentent la voiture, et d'autres la montagne ? Il n'y a aucune segmentation préalable. L'assignation spatiale est entièrement émergente — elle naît de trois mécanismes combinés.
Le modèle a été entraîné sur des millions d'images légendées. Dans toutes les images "voiture sur route de montagne", la voiture est statistiquement au centre-bas, la montagne en arrière-plan, le ciel en haut. Le modèle n'a pas appris de règles explicites — il a internalisé cette distribution. Dès le début du débruitage, il génère du bruit structuré qui reflète ces priors spatiaux.
L'assignation se construit step par step. Au step T, un patch qui ressemble légèrement à une voiture (dans l'espace latent) va attirer un peu plus d'attention sur le token "voiture". Cela oriente sa prédiction au step T−1 vers quelque chose d'encore plus "voiture". Ce patch attire maintenant encore plus d'attention sur "voiture". Et ainsi de suite — la boucle converge en quelques dizaines de steps vers une assignation stable.
Des tokens comme "plan large" ou "cinématique" n'ont pas de région assignée — ils influencent faiblement tous les patches en même temps. Ce sont des modificateurs de style global : composition, ratio, grain, contraste. Un patch "voiture" attend à la fois fortement sur "voiture" et faiblement sur "cinématique". C'est ce double signal qui produit une voiture avec un rendu cinématique, pas une voiture ou un rendu cinématique.
Conséquences pratiques pour le prompting
- Le bleeding de couleur : "voiture rouge sur route rouge" — les tokens "rouge" sont disputés entre deux zones spatiales voisines. La couleur peut "fuir" d'un objet à l'autre. Solution : différencier clairement ("carrosserie rouge vif" + "asphalte gris").
- Les descripteurs spatiaux aident : "en arrière-plan flou", "au premier plan", "à gauche" donnent des indices statistiques que le modèle peut exploiter. Ils ne garantissent rien mais réduisent l'ambiguïté de l'assignation.
- Les objets multiples du même type sont difficiles : "trois voitures" — le modèle doit assigner trois zones distinctes au même token. Les priors d'entraînement rendent ça moins stable qu'un seul objet.
- Les modificateurs globaux amplifient tout : "hyperréaliste, 8K, cinématique" agissent sur la totalité de l'image. Les placer en début ou fin de prompt change peu de choses — leur effet est intrinsèquement diffus.
05 // ControlNet — Conditionner la structure spatiale
La cross-attention texte répond à "quoi ?". ControlNet répond à "où ?" — quelle structure géométrique la génération doit respecter. Une depth map ne dit pas "génère une voiture ici" : elle dit "génère quelque chose de proche ici". La cross-attention texte décide ensuite que ce quelque chose de proche est une voiture, un rocher, ou un personnage. Texte et structure spatiale fonctionnent en parallèle, sans se remplacer.
La branche parallèle gelée
ControlNet ajoute une copie gelée de l'encodeur UNet — une branche distincte dont les poids ne bougent jamais pendant l'inférence. Cette copie traite l'image de contrôle (depth, canny, pose…) et injecte ses features dans le décodeur du UNet principal par des connexions résiduelles, à plusieurs niveaux de résolution simultanément. Les patches reçoivent la contrainte spatiale avant d'entrer dans les couches de cross-attention : le texte sculpte le contenu dans une enveloppe géométrique qu'il ne contrôle pas lui-même.
Depth map et Canny — deux types de contraintes
Les deux modes agissent sur des aspects différents de la structure et se combinent souvent dans les pipelines de production.
Une depth map ControlNet fonctionne comme votre passe Z-depth en compositing : elle encode la profondeur relative de chaque pixel. Sauf qu'ici, au lieu de séparer les plans en post, elle contraint la génération — ce qui est proche reste proche, ce qui est loin reste loin. Le Canny correspond à un matte de contour ou un wireframe : vous préservez la silhouette, la génération remplit librement l'intérieur. Combinez les deux pour une scène où la composition 3D et les silhouettes sont contrôlées simultanément.
La force du ControlNet (strength)
Le paramètre strength (ou control weight dans ComfyUI) règle combien le signal ControlNet pèse lors de l'injection résiduelle. À force haute, la structure est strictement respectée. À force basse, le texte a plus de liberté pour dévier.
texte seul
créativité conservée
style pur, transfer
usage standard
depth, pose, canny
artefacts, halos
rarement utile
Ce que ControlNet n'est pas
- ≠ Image de référence (IPAdapter) — IPAdapter transfère un style ou une apparence visuelle globale. ControlNet contraint une structure géométrique locale, pixel par pixel. Un canny de voiture avec le prompt "vaisseau spatial" donne une silhouette de voiture avec une apparence de vaisseau — pas une copie de voiture.
- ≠ Inpainting — L'inpainting agit sur une région masquée. ControlNet contraint la structure sur toute l'image simultanément, sans masque.
- ≠ Prompt spatial ("en avant-plan", "à gauche") — Le prompt donne des indices statistiques sur la composition. ControlNet est une contrainte dure : la relation pixel/patch est directe et quantifiée par le signal d'injection.
06 // Le coût quadratique — Pourquoi la VRAM explose
Voici la source de tous vos crashs "out of memory". La matrice Q·Kᵀ a une taille de N×N où N est le nombre de patches. Doublez la résolution : N quadruple, la mémoire explose d'un facteur 16.
Générer à 1024×1024 sans optimisation requiert de matérialiser une matrice d'attention de plusieurs gigaoctets en VRAM — là où la plupart des cartes grand public plafonnent. Les méthodes suivantes ne changent pas le résultat mathématique, elles changent uniquement la façon d'exécuter ce même calcul pour éviter ce pic.
En ray tracing brut, doubler la résolution de l'image quadruple le nombre de rayons. La solution (BVH, denoising DLSS, importance sampling) ne change pas le résultat visuel voulu — elle change comment on y arrive en consommant moins de mémoire et de temps. Exactement ce que font Flash Attention et Sage Attention pour la mémoire GPU.
07 // Les 4 méthodes d'attention dans ComfyUI
ComfyUI propose quatre implémentations du même calcul. Le résultat devrait être mathématiquement identique (sauf Sage, qui fait un compromis délibéré). Seule la façon de gérer la mémoire et le matériel change.
Performances comparées — génération à 1024×1024, 20 steps
Mesures indicatives sur RTX 3080 10 Go. Votre résultat variera selon le modèle et la configuration.
Barres = temps de génération (plus court = plus rapide). Flash Attention + SDP donnent un résultat identique bit-à-bit. Sage Attention peut diverger légèrement.
08 // Quel profil, quelle méthode ?
Un arbre de décision en 3 questions :
Dans 90% des cas, PyTorch SDP (actif par défaut) est votre meilleure option. Activez Flash Attention si vous avez une RTX 3060+ (Ampere) pour gagner 20% de vitesse sur l'image. Ajoutez Sage Attention uniquement pour la vidéo ou la très haute résolution.
09 // Cheat Sheet
| Méthode | Résultat | Vitesse | VRAM | Cas d'usage idéal |
|---|---|---|---|---|
| PyTorch SDP | Exact | Très rapide | −50–70% | Défaut — tout le monde |
| xFormers | Exact | Rapide | −50% | VAE, cartes med. gamme |
| Flash Attention | Exact | Le plus rapide | Optimal | RTX 3060+ (Ampere) image HD |
| Sage Attention | ≈ Approx. | Très rapide | Très bas | Vidéo, >2048 px, vieilles cartes |
Les deux types d'attention — récapitulatif
| Type | Source de Q | Source de K, V | Rôle | Analogie 3D |
|---|---|---|---|---|
| Self-Attention | Image latente | Image latente | Cohérence interne de l'image | Global Illumination |
| Cross-Attention | Image latente | Tokens texte | Ancrage sémantique du prompt | UV lookup inversé |
L'attention est le mécanisme qui transforme du bruit aléatoire en image cohérente. Sa nature globale (tout parle à tout) est la source à la fois de sa puissance — la cohérence stupéfiante des générations modernes — et de son coût quadratique. Toutes les optimisations (Flash, Sage, xFormers) cherchent à préserver cette puissance en résolvant ce coût.