PartaGPU : mutualiser la puissance de calcul d'une salle pour entraîner ses modèles IA plus vite

10 May 2026 . category: tech . Comments
#ia #gpu #calcul-distribué #opensource #deep-learning #pytorch #ddp #rust #cybersécurité

Logo PartaGPU

Résumé — Pendant ma formation DE EIA, j’ai été confronté à un problème pratique : certains entraînements de modèles IA prenaient des heures sur ma seule machine, alors que les postes voisins de la salle restaient inactifs. J’ai donc développé PartaGPU, une application open source qui permet à plusieurs ordinateurs d’une même salle de partager leur puissance de calcul (CPU, GPU, RAM) pour exécuter des entraînements distribués. Concrètement, je suis passé d’un entraînement de UNet de 1h30 en solo à 30 minutes à 4 machines. Cet article présente l’application, son architecture (cgroups v2, mDNS, PyTorch DDP, crypto bout-en-bout) et comment la prendre en main.

Le problème : du calcul partout, mais sous-utilisé

Dans une salle de cours d’informatique, on dispose typiquement de 10 à 20 stations de travail équipées de GPU. Mais en pratique, à un instant donné :

  • une partie des postes est inutilisée (élèves absents, en pause, en train de lire la doc) ;
  • ceux qui tournent ne saturent presque jamais leurs ressources ;
  • celui qui lance un entraînement long (segmentation d’image, fine-tuning, etc.) doit le subir seul.

Pendant que mon UNet tournait pendant 1h30 sur ma machine, les 19 autres GPU de la salle dormaient. Le constat est frustrant, et il devient absurde quand on multiplie les expériences.

L’idée de PartaGPU est née de là : permettre à n’importe quel poste de la salle de prêter une fraction configurable de ses ressources, et permettre à n’importe quel autre poste de consommer cette puissance disponible — le tout avec un contrôle fin de qui partage quoi, et avec qui.

Illustration du concept : un poste coordinateur répartit une charge d'entraînement sur plusieurs machines de la salle.

Illustration du concept : un poste coordinateur répartit une charge d’entraînement sur plusieurs machines de la salle.

Ce que fait PartaGPU concrètement

PartaGPU se compose de deux briques :

  1. Une application de bureau (Tauri = backend Rust + frontend React/TypeScript) installée sur chaque poste. Elle affiche les ressources locales, permet de régler par curseur la part de CPU / RAM / GPU qu’on accepte de partager, et expose les pairs disponibles dans la salle.
  2. Un paquet Python partagpu côté client, qui découvre les machines disponibles et orchestre l’exécution distribuée. Une seule ligne suffit pour lancer un entraînement réparti :
import partagpu

partagpu.distribute("train.py")  # PyTorch DDP sur tous les GPU de la salle

L’application embarque également :

  • des salles virtuelles protégées par un code à 4 mots (par exemple pomme-tigre-bleu-ocean), pour cloisonner les groupes et empêcher un poste non autorisé de rejoindre la grappe ;
  • un mode pause / désactivation propre, qui rend les ressources locales en quelques secondes ;
  • une vue parc qui donne en temps réel l’état des machines et de leur charge ;
  • un onglet Guide bilingue FR/EN.

Les gains observés

Voici le benchmark qui m’a convaincu de continuer le projet, sur un entraînement de UNet pour de la segmentation médicale :

Configuration Temps d’entraînement Speedup
1 machine (référence) 1h30
4 machines via PartaGPU 30 min

Le gain n’est pas linéaire — c’est attendu. La communication inter-nœuds (synchronisation des gradients en DDP), la latence réseau et le coût d’orchestration introduisent un overhead qui réduit l’efficacité au-delà d’un certain nombre de pairs1. Je prévois de réaliser une série de tests plus systématiques (sur différents types de modèles : UNet, ResNet, Transformers) pour dégager une courbe de gain en fonction du nombre de machines, de la taille du batch et de la bande passante. Mais même avec une efficacité de 75 %, multiplier par 3 le rendement d’une session d’entraînement change concrètement la manière de travailler en salle de cours.

Architecture technique

La conception de PartaGPU s’est faite autour de quatre exigences : simplicité d’usage, isolation forte, découverte automatique, sécurité par défaut.

Isolation des charges : cgroups v2 et bubblewrap

Quand un pair accepte d’exécuter une tâche pour le compte d’un autre poste, on ne peut pas se permettre de laisser ce code accéder à toute la machine. PartaGPU s’appuie sur :

  • les cgroups v2 du noyau Linux pour appliquer les plafonds de CPU et de RAM choisis par l’utilisateur via les curseurs. C’est la même primitive que celle utilisée par Docker, mais sans la complexité d’un démon Docker à installer sur chaque poste : PartaGPU écrit directement dans les fichiers cgroup ;
  • bubblewrap (bwrap) pour la sandbox du processus distant : système de fichiers en lecture seule, /workspace en tmpfs, passthrough GPU, réseau désactivé par défaut ;
  • CUDA MPS pour faire respecter le plafond de % GPU partagé.

Côté privilèges, seules quatre actions root passent par PolicyKit (pkexec) : la création initiale d’un compte système partagpu, son mot de passe, la mise en place du cgroup, et la suppression du compte. Aucune action utilisateur courante (déplacer un curseur, accepter une tâche) ne déclenche d’élévation de privilèges.

Découverte automatique : mDNS

Pour qu’un poste sache quels autres postes sont disponibles dans la salle, PartaGPU utilise mDNS (Multicast DNS, le même protocole que Bonjour/Avahi). Chaque nœud annonce sur le réseau local sa présence ainsi que des métadonnées utiles (nombre de GPU, version). Pas de serveur central, pas de configuration manuelle d’IP : on branche, on lance, ça se découvre.

Distribution du calcul : PyTorch DDP

Une fois les pairs identifiés, l’orchestration de l’entraînement repose sur PyTorch Distributed Data Parallel (DDP). Le paquet Python partagpu se charge :

  • de découvrir tous les GPU disponibles dans la salle (discover()) ;
  • de pousser le workspace (jusqu’à 16 Mo) sur chaque pair ;
  • de lancer le script via DDP (distribute()) en gérant automatiquement les machines multi-GPU ;
  • de relayer en streaming stdout / stderr vers le client ;
  • de récupérer les artefacts produits (par exemple model.pt, jusqu’à 256 Mio) ;
  • de propager Ctrl+C à tous les nœuds en cas d’annulation.

Sécurité : un peu de crypto

C’est probablement la partie sur laquelle je me suis le plus amusé, et qui m’a rappelé ma scolarité DE ECIN. Le modèle de menace est simple : on suppose que n’importe qui sur le réseau local peut tenter de rejoindre la grappe, d’écouter les échanges ou d’injecter une charge de travail malicieuse. Les contre-mesures :

  • Authentification de la salle (HMAC + PBKDF2). Le code à 4 mots est dérivé via PBKDF2-HMAC-SHA256 (600 000 itérations, ~100 ms — conforme aux recommandations NIST SP 800-132 et OWASP) en une clé d’authentification 256 bits. Chaque pair est challengé par un nonce HMAC et la vérification est rejouée toutes les 60 secondes. La comparaison est faite en temps constant pour éviter les attaques par mesure de durée.
  • Chiffrement bout-en-bout (X25519 ECDH + AES-256-GCM). Toutes les communications entre pairs (port 7655) sont chiffrées par AES-256-GCM, avec une clé dérivée par échange Diffie-Hellman X25519 éphémère à chaque requête. La clé éphémère du serveur n’est conservée qu’en RAM et est renouvelée toutes les 10 minutes pour assurer la forward secrecy.
  • Anti-rejeu. Chaque requête transporte un en-tête X-PartaGPU-AUTH: <timestamp>:<HMAC> qui lie le corps de la requête à un timestamp dans une fenêtre glissante de 30 secondes.
  • Journal de sécurité. Un ring buffer enregistre tous les événements suspects (pair inconnu rejeté, HMAC invalide, etc.) consultables depuis l’application.

Le tout reste auditable : le code est ouvert, les choix cryptographiques sont documentés, et il n’y a aucune dépendance à un service tiers.

Comment l’utiliser

Dans la mesure où il s’agit d’un projet utile dans le cadre d’une scolarité liée à l’IA, le cas métier le plus représentatif est celui de l’utilisation de PartaGPU dans un Jupyter Notebook. Le dépôt fournit un notebook Jupyter d’exemple pour prendre en main l’API Python. Côté installation :

  • Option recommandée : un paquet .deb est fourni dans les releases GitHub. sudo dpkg -i partagpu_*_amd64.deb installe l’application, le helper, la règle PolicyKit et le réglage sysctl nécessaire pour bubblewrap sur Ubuntu 24.04+.
  • Alternative portable : une AppImage est également disponible.
  • Depuis les sources : git clone … && npm install && npm run tauri:dev.
  • Côté client Python : pip install partagpu.

Le flux d’utilisation typique :

  1. Lancer l’application sur tous les postes participants.
  2. Sur chaque poste, ouvrir la même salle via le code à 4 mots.
  3. Régler les curseurs CPU / RAM / GPU selon ce qu’on accepte de partager.
  4. Depuis un notebook ou un script, appeler partagpu.distribute("train.py").

Limites actuelles et perspectives

Le projet est jeune, et plusieurs pistes restent à explorer :

  • Caractériser finement la courbe de gain en fonction du modèle, du nombre de pairs, de la bande passante. L’objectif est de produire une formule empirique qui aide l’utilisateur à décider combien de pairs solliciter pour un entraînement donné.
  • Étendre le support au-delà de Linux : la sandbox bubblewrap et les cgroups sont spécifiques à Linux. Le portage macOS / Windows nécessitera de remplacer ces briques par leurs équivalents (App Sandbox, AppContainer, Job Objects).
  • Tolérance aux pannes : aujourd’hui, si un nœud disparaît au milieu d’un entraînement, le job échoue. Mettre en place des points de reprise (checkpointing coordonné) et de la redondance améliorerait la robustesse.
  • Élargir au-delà de PyTorch DDP : Tensorflow, JAX, et les workloads non-IA (rendu, simulation).

Conclusion

PartaGPU est avant tout un outil que j’utilise moi-même pour mes prochains entraînements, et que je rends public au cas où il intéresserait d’autres étudiants, enseignants ou laboratoires confrontés au même paradoxe : du calcul partout, mais mal mutualisé. Le code est disponible sur github.com/cesar-lizurey/partagpu sous licence ouverte.

Toute remarque, contribution, rapport de bug ou retour d’expérience est bienvenu — ouvrez une issue ou une pull request sur le dépôt. Et si vous lancez un entraînement avec, n’hésitez pas à me partager votre courbe de gain : ça nourrira l’étude empirique du speedup que je compte mener.


Liens utiles

  1. La loi d’Amdahl et les phénomènes de communication overhead expliquent pourquoi la mise à l’échelle de l’entraînement distribué n’est jamais linéaire. Voir PyTorch DDP docs et Goyal et al., Accurate, Large Minibatch SGD


Me

César Lizurey est un gendarme ayant occupé des fonctions de commandement mais également d'état-major, en tant que chef de projet ou dans le domaine de l'innovation et de la prospective. Il aime coder, faire de la musique et le sport. Et coder.