Comment exécuter un serveur de diffusion stable sur Google Cloud Platform (GCP)
Un guide étape par étape pour créer et déployer une application Flask
Depuis que Stability.ai a publié Stable Diffusion (leur modèle de texte à image open source) il y a quelques semaines à peine, la communauté ML est folle des portes qu’elle ouvre. En tant qu’alternative open source au DALL·E 2 fermé d’OpenAI avec une qualité comparable, Stable Diffusion offre quelque chose à tout le monde : les utilisateurs finaux peuvent générer des images pratiquement gratuitement, les développeurs peuvent intégrer le modèle dans leur service, les ingénieurs ML peuvent étudier et modifier le code, et les chercheurs ont toute latitude pour pousser l’état de l’art encore plus loin.
Malgré l’avalanche de tutoriels sur la façon d’exploiter Stable Diffusion, je n’ai pas trouvé de recette vérifiée pour héberger le modèle moi-même. Mon objectif est d’émettre des requêtes HTTP vers mon propre service dans le confort de mon navigateur. Aucune limite de crédit, aucun problème de connexion, personne n’espionne mes images. Je me suis donc lancé dans une quête d’une journée pour créer et déployer un serveur Web Stable Diffusion sur Google Cloud.

Cet article reprend tous les petits détails pénibles que j’ai dû régler, en espérant que cela vous fera gagner du temps. Voici les étapes de haut niveau (nous approfondirons chacune d’entre elles ci-dessous) :
- Assurez-vous d’avoir suffisamment de quota GPU
- Créer une machine virtuelle avec un GPU attaché
- Télécharger Stable Diffusion et tester l’inférence
- Regroupez Stable Diffusion dans une application Flask
- Déployez et rendez votre serveur Web accessible au public
1. Assurez-vous d’avoir suffisamment de quota GPU
Étant donné que les GPU ne sont toujours pas bon marché, Google gère un navire serré en ce qui concerne sa flotte de GPU, fournissant son offre limitée à ceux qui en ont le plus besoin et à ceux qui sont prêts à payer. Par défaut, les comptes d’essai gratuits n’ont pas de quota GPU. Pour vérifier votre quota GPU :
Navigation (hamburger menu) > IAM & Admin > Quotas
et CTRL+F
pour « GPU (toutes régions) ». Si votre limite est de 0 ou si votre pourcentage d’utilisation actuel est de 100 %, vous devrez demander un quota supplémentaire. Sinon, vous pouvez passer à l’étape 2 ci-dessous.
Pour augmenter votre quota, sélectionnez la ligne « GPU (toutes régions) », puis cliquez sur le EDIT QUOTAS
bouton (en haut à droite de la console). Pour ce tutoriel, vous aurez besoin d’un seul GPU, alors augmentez votre quota de 1. Notez que vous devrez inclure une justification dans votre demande — assurez-vous d’expliquer pourquoi un CPU ne peut pas satisfaire votre besoin . Ma demande initiale, qui ne comprenait qu’une note insipide, a été rejetée. Lors de ma deuxième tentative (et réussie), j’ai explicitement indiqué que je travaillais avec un gros modèle ML qui nécessite un GPU. Notez que si votre demande est examinée par un humain, cela peut prendre 2 à 3 jours ouvrables ; si vous suivez le ticket et expliquez votre urgence, ils pourraient répondre plus rapidement.
2. Créez une machine virtuelle avec un GPU attaché
Une fois que vous avez un quota de GPU, vous pouvez maintenant créer une instance de machine virtuelle (VM) avec un GPU attaché.
Depuis la navigation (menu hamburger) : Compute Engine > VM instances
. Cliquez ensuite sur CREATE INSTANCE
(en haut à gauche de la console). Pour des instructions générales sur la manière de remplir ce formulaire, vous pouvez suivre ce guide officiel ; ici, je vais me concentrer sur les paramètres particulièrement pertinents pour l’exécution de Stable Diffusion :
- Série : Sélectionner
N1
- Type de machine : Sélectionnez
n1-standard-4
. C’est l’option la moins chère avec suffisamment de mémoire (15 Go) pour charger Stable Diffusion. Malheureusement, la prochaine option la moins chère (7,5 Go) ne suffit pas et vous manquerez de mémoire lors du chargement du modèle et de son transfert vers le GPU. - Type de GPU : développez
CPU PLATFORM AND GPU
et cliquez sur leADD GPU
bouton. SélectionnezNVIDIA Tesla T4
– c’est le GPU le moins cher et il fait le travail (il dispose de 16 Go de VRAM, ce qui répond aux exigences de 10 Go de Stable Diffusion). Si vous êtes curieux, jetez un œil au tableau comparatif et au tableau des prix . Notez que vous pouvez rendre le GPU préemptif pour obtenir un meilleur prix (c’est-à-dire que Google le récupérera chaque fois qu’il en aura besoin pour des tâches plus prioritaires), mais je trouve personnellement cela frustrant même en jouant. - Image : faites défiler vers le bas
Boot disk
et cliquez surSWITCH IMAGE
. Pour le système d’exploitation, sélectionnezDeep Learning on Linux
; pour la version, sélectionnezDebian 10 based Deep Learning VM with CUDA 11.0 M95
. - Accès : en supposant que vous souhaitiez rendre votre serveur accessible au public : (a) sous
Identity and API access
, sélectionnezAllow default access
et (b) sousFirewall
, sélectionnezAllow HTTP traffic
etAllow HTTPS traffic
.
Enfin, cliquez sur le CREATE
bouton. Notez que cela peut devenir assez cher (l’estimation mensuelle est d’environ 281 $ au moment de la rédaction).

3. Téléchargez Stable Diffusion et testez l’inférence
Une fois l’instance de VM créée, accédez-y via SSH. Vous pouvez soit choisir l’option « SSH-in-browser » depuis la console, soit exécuter la commande suivante depuis votre terminal :
gcloud compute ssh --zone <nom-zone> <nom-machine> --project <nom-projet>
Lors de votre première connexion, vous aurez la possibilité d’installer les pilotes GPU nécessaires. Assurez-vous d’accepter en tapant « y »:
Souhaitez-vous installer le pilote Nvidia ? [o/n]
Ensuite, vérifions que vous pouvez exécuter l’inférence de diffusion stable localement. Tout d’abord, téléchargez les artefacts nécessaires :
# Cloner le dépôt public Github. git clone https://github.com/CompVis/stable-diffusion.git# Créer un environnement virtuel Python. cd stable-diffusion conda env créer -f environnement.yaml conda activer ldm
Nous utiliserons la diffusers
bibliothèque de HuggingFace pour tester l’inférence. Créez un nouveau fichier appelé inference.py
avec le contenu suivant :
importer la torche depuis la torche importer la diffusion automatique depuis les diffuseurs importer StableDiffusionPipelineassert torch.cuda.is_available()pipe = StableDiffusionPipeline.from_pretrained( "CompVis/stable-diffusion-v1-4", use_auth_token=True ).to("cuda") prompt = "une photo d'un astronaute à cheval sur mars" avec autocast("cuda") : image = pipe(prompt)["sample"][0] image.save("astronaut_rides_horse.png")
Ensuite, connectez-vous à HuggingFace via la console, puis exécutez le script d’inférence :
huggingface-cli login # Entrez le jeton d'accès de votre compte HuggingFace.python inference.py
Cette invocation peut échouer et vous diriger vers un lien HuggingFace, où vous êtes censé accepter les termes et conditions d’utilisation de Stable Diffusion (ils veulent juste que vous reconnaissiez que vous n’êtes pas mauvais). Une fois que vous avez coché cette case, réexécutez le code d’inférence (ce qui devrait prendre environ 15 secondes) et assurez-vous que vous pouvez trouver l’image générée sous austronaut_rides_horse.png
. Pour le télécharger sur votre machine afin de le visualiser, vous pouvez utiliser gcloud compute scp
.
4. Regroupez Stable Diffusion dans une application Flask
Maintenant que vous avez vérifié que l’inférence fonctionne correctement, nous allons créer un serveur Web en tant qu’application Flask. À chaque requête, le serveur lit le prompt
paramètre, exécute l’inférence à l’aide du modèle de diffusion stable et renvoie l’image générée. Pour commencer, installez Flask et créez un répertoire pour l’application :
pip install Flask
cd ~; mkdir flask_app
Collez cette simple application Flask dans un fichier appeléapp.py
:
depuis l'importation de la fiole Flask, request, send_file import io import torch from torch import autocast from diffusers import StableDiffusionPipelineapp = Flask(__name__) assert torch.cuda.is_available()pipe = StableDiffusionPipeline.from_pretrained( "CompVis/stable-diffusion-v1-4", use_auth_token=True ).to("cuda")def run_inference(prompt): with autocast("cuda") : image = pipe(prompt)["sample"][0] img_data = io.BytesIO() image.save(img_data, "PNG") img_data.seek(0 ) renvoie img_data@app .route('/') def myapp() : si "prompt" n'est pas dans request.args : return "Veuillez spécifier un paramètre d'invite", 400 prompt = request.args["prompt"] img_data = run_inference(prompt) return send_file(img_data, mimetype='image/png')
Notez que cette application est très simple et qu’elle renvoie simplement l’image brute. Une application plus pratique renverrait un formulaire HTML avec un champ de saisie pour l’invite et potentiellement d’autres boutons (comme les dimensions d’image souhaitées). GradIO et Streamlit sont d’excellentes bibliothèques pour créer des applications plus élaborées.
Vérifiez maintenant que l’application Flask s’exécute sans erreur :
export FLASK_APP=app
export FLASK_DEBUG=true
flask run
Cela devrait démarrer le serveur sur localhost au port 5000. Vous ne pourrez pas encore accéder à ce serveur à partir d’un navigateur, car le port 5000 n’est pas accessible par défaut.
5. Déployez et rendez votre serveur accessible au public
Bien que le serveur par défaut de Flask convienne au développement, il est courant de déployer une application Flask en production à l’aide de gunicorn . Je ne couvrirai pas les raisons ici, mais vous pouvez lire cette excellente explication de la raison pour laquelle le gunicorn est préféré. Pour l’installer, lancez simplement pip install gunicorn
. Pour lancer le serveur Web, exécutez la commande suivante :
gunicorn -b :5000 --timeout=20 app:app
Le -b
paramètre définit le port souhaité. Vous pouvez le remplacer par n’importe quel autre port non utilisé. Le --timeout
paramètre définit le nombre de secondes avant que gunicorn ne réinitialise ses travailleurs, en supposant que quelque chose s’est mal passé. Étant donné que l’exécution d’une passe avant dans le modèle de diffusion stable prend en moyenne 15 secondes, réglez le délai d’attente sur au moins 20 secondes.
Si vous voulez que le serveur survive après vous être déconnecté de l’instance de VM, vous pouvez utiliser l’ nohup
utilitaire Linux (c’est-à-dire « pas de problème ») :
nohup gunicorn -b :5000 --timeout=20 app:app &
L’esperluette finale envoie le processus s’exécuter en arrière-plan (vous reprenez donc le contrôle de la ligne de commande). Les journaux seront exportés vers un fichier appelé nohup.out
, généralement placé dans le répertoire où vous avez exécuté la commande.
Création d’une règle de pare-feu pour rendre le port accessible
La dernière étape consiste à adresser des requêtes à ce serveur à partir d’un navigateur. Pour ce faire, nous devons rendre votre port accessible.
Depuis la navigation (menu hamburger) : VPC Network > Firewall
. Dans le menu du haut, cliquez sur CREATE FIREWALL RULE
. Dans le formulaire, définissez les éléments suivants :
- Nom : allow-stable-diffusion-access (ou votre nom préféré)
- Journaux : activés
- Sens de circulation : Entrée
- Action sur match : Autoriser
- Cibles : Balises cibles spécifiées
- Balises cibles : deeplearning-vm (Cette balise est automatiquement ajoutée à votre VM lorsque vous choisissez l’image « Deep Learning on Linux ». Vous pouvez ajouter manuellement une autre balise à votre VM et la référencer ici.)
- Protocoles et ports : TCP — 5000, ou votre port choisi.
Une fois le formulaire rempli, cliquez sur CREATE
.
Envoi de requêtes au serveur Web à partir d’un navigateur
Enfin, trouvez l’adresse IP de votre VM (depuis le menu de navigation, COMPUTE ENGINE > VM INSTANCES
et regardez la colonne « IP externe » de votre VM. Si l’adresse IP est 12.34.56.789, alors votre serveur web est accessible à http://12.34.56.789 :5000 .
N’oubliez pas que le serveur attend un paramètre appelé prompt
, que nous pouvons envoyer en tant que paramètre HTTP. Pour l’invite « robot dancing », voici à quoi ressemble l’URL :
Assurez-vous que le navigateur n’utilise pas automatiquement par défaut https
(au lieu de http
, car nous n’avons pas de certificat SSL configuré).

Avis de non-responsabilité : ce serveur n’est pas prêt pour la production
Il existe de nombreuses raisons pour lesquelles ce serveur Web n’est pas prêt pour une utilisation en production, mais le plus gros goulot d’étranglement est son périphérique GPU unique. Étant donné que l’exécution de l’inférence nécessite 10 Go de VRAM (et que notre GPU ne dispose que de 15 Go de mémoire), gunicorn ne peut pas se permettre d’élever plus d’un travailleur. En d’autres termes, le serveur ne peut traiter qu’une seule requête à la fois (dont la résolution prend 15 secondes).
Pour les tâches moins intensives en calcul, la solution standard est constituée de plates-formes de « micro-services conteneurisés sans serveur » comme Google Cloud Run (GCR) ; AWS et Azure proposent des offres analogues. Les développeurs regroupent leurs applications Web dans des conteneurs (environnements de calcul autonomes qui contiennent toutes les dépendances nécessaires pour exécuter l’application, comme Docker) et transférez-les dans le cloud. GCR déploie ces conteneurs sur des machines réelles et adapte le déploiement en fonction de la demande (le nombre de requêtes par seconde) ; si nécessaire, GCR peut allouer des dizaines de milliers de CPU à votre service et ainsi le rendre hautement disponible. Vous n’avez pas à vous soucier de désactiver vous-même les serveurs ou de les redémarrer lorsqu’ils meurent. Le modèle de facturation est également pratique pour l’utilisateur, qui finit par payer à l’utilisation (au lieu de devoir entretenir en permanence un nombre fixe de machines).
Cependant, depuis septembre 2022, Google Cloud Run ne prend pas en charge les GPU. Étant donné que le coût d’acquisition et de fonctionnement d’un GPU est encore assez élevé, il n’est pas très surprenant que Google reste protecteur de l’utilisation du GPU. On ne peut que supposer que les algorithmes de GCR pour la mise à l’échelle automatique ne peuvent pas empêcher les appareils d’être inactifs pendant une bonne partie du temps ; alors qu’un CPU inactif n’est pas une grosse perte, laisser un GPU inutilisé représente un coût d’opportunité plus important. De plus, ils veulent probablement éviter les situations dans lesquelles les gens surdimensionnent aveuglément et sont confrontés à des factures monstrueuses à la fin du mois.
En passant, Google Cloud Run pour Anthos commence à proposer des GPU, mais il s’agit d’un service destiné aux utilisateurs expérimentés/clients haut de gamme qui ont besoin d’une interopérabilité entre plusieurs clouds et environnements sur site. Ce n’est certainement pas pour les passionnés de ML qui souhaitent créer leur propre serveur Web Stable Diffusion.
Alternatives à l’exécution de votre propre serveur
Bien qu’il ait été amusant de rechercher la meilleure façon de diffuser Stable Diffusion via Google Cloud, ce n’est pas nécessairement le moyen le plus efficace de générer des images AI. En fonction de vos besoins, les workflows suivants peuvent être plus appropriés :
- Pour les utilisateurs non techniques : rendez-vous sur Dreamstudio , le service officiel de Stability.ai, où vous obtenez des crédits gratuits.
- Pour les passionnés de ML qui veulent juste s’amuser : utilisez Google Colab . Avec le niveau gratuit, vous bénéficiez d’un accès GPU chaque fois qu’il est disponible. Pour 10 $/mois, vous pouvez passer à Colab Pro , qui promet « des GPU plus rapides et plus de mémoire ».
- Pour les développeurs cherchant à intégrer Stable Diffusion dans leur service : appelez l’API depuis Replicate , pour 0,0023 $/seconde. Ils garantissent que 80 % des appels se terminent en 15 secondes, de sorte que le 80e centile de coût pour une image est d’environ 0,0345 $. Replicate est similaire au plus connu HuggingFace , mais se concentre davantage sur la vision par ordinateur que sur le traitement du langage naturel. Pour l’instant, HuggingFace n’offre pas son API standard « Accelerated Inference » pour la diffusion stable, mais c’est très probablement en cours.