Expert Cybersécurité & IAv9.0
Centres de ressources conformité
Besoin d'un accompagnement expert ?
Devis personnalisé sous 24h — audit, conformité, incident
Checklists Sécurité — Audit & Durcissement
Formats disponibles
📄 PDF 📊 Excel 🌐 Web

11 checklists professionnelles couvrant 2 200+ points de contrôle. Téléchargement gratuit, aucune inscription.

Aller au contenu Aller au quiz
Lu

Multi-GPU et NCCL

En route — chaque ligne compte.

~30 min
Programme complet

Multi-GPU et NCCL

Topologie PCIe/NVLink/NVSwitch, mécanique des collectives AllReduce, mise en œuvre avec NCCL et PyTorch DDP, stratégies de sharding pour l'entraînement et l'inférence, et arithmétique de la rentabilité du multi-GPU.

Ch. 8/12 Avancé
Table des matières

    Pourquoi la topologie compte avant le code

    Ajouter des GPUGPUIAProcesseur graphique parallélisant massivement les calculs matriciels ; indispensable à l'entraînement et à l'inférence des modèles de deep learning.Voir dans le glossaire à un job d'entraînement ne divise pas automatiquement le temps d'exécution par le nombre de cartes. C'est l'erreur la plus fréquente au passage du mono-GPU au multi-GPU : on raisonne en FLOPS cumulés en oubliant que chaque GPU supplémentaire doit désormais échanger des donnéesdonnéesIAEnsemble d'informations structurées ou non utilisées pour entraîner, évaluer ou alimenter un modèle. La qualité, la quantité et la représentativité des données sont les facteurs décisifs pour les performances en apprentissage automatique.Voir dans le glossaire avec les autres à chaque étape d'optimisation. La vitesse de ces échanges dépend directement de la topologie matérielle, et cette topologie fixe un plafond de performance que le code applicatif ne peut pas contourner.

    Ce chapitre part de la couche physique — comment les GPU sont reliés entre eux et entre nœuds — pour remonter vers la couche logicielle : NCCL, PyTorch DDP, stratégies de sharding. Il se termine par la question qui compte réellement en production : à partir de quel point le multi-GPU cesse d'être rentable.

    Topologie multi-GPU : GPU reliés par NVSwitch au sein d'un nœud, nœuds reliés par un réseau InfiniBand ou Ethernet RDMA
    La bande passante chute d'un ordre de grandeur en sortant du nœud : c'est là que se joue le scaling multi-nœud.

    Interconnexions : PCIe, NVLink, NVSwitch, réseau

    Trois échelles de communication coexistent dans un cluster GPU, avec des ordres de grandeur très différents :

    Lien Bande passante typique Portée
    PCIe Gen4 x16 ~32 Go/s bidirectionnel GPU vers CPU, ou GPU vers GPU si pas de NVLink
    NVLink 4e génération ~900 Go/s cumulés par GPU (H100) Intra-nœud, pair-à-pair direct
    NVSwitch non bloquant, agrège les liens NVLink Intra-nœud, tous-vers-tous
    InfiniBand NDR / Ethernet RDMA ~40 à 50 Go/s par lien (200–400 Gb/s) Inter-nœuds

    Deux GPU reliés uniquement par PCIe et transitant par le CPU pour échanger des données subissent une latence et une bande passante très inférieures à deux GPU reliés par NVLink. Sur des serveurs multi-GPU sans NVSwitch, la topologie peut même varier par paire : deux cartes sur le même pont PCIe communiquent plus vite qu'une paire séparée par un pont NUMA. nvidia-smi topo -m affiche cette matrice et doit être la première commande lancée sur toute nouvelle machine avant d'y planifier un job distribué.

    Ne présumez jamais qu'une instance cloud « 8x GPU » dispose de NVSwitch. Certaines offres d'entrée de gamme relient les GPU par paires PCIe sans pont haut débit. Le même code de training peut afficher une efficacité de scaling de 90 % sur une instance et de 55 % sur une autre, pour un prix horaire comparable. Vérifiez la topologie avant de signer un contrat de réservation longue durée.

    À l'échelle du cluster, le réseau inter-nœuds devient le goulot d'étranglement dominant : un lien InfiniBand NDR à 400 Gb/s, soit environ 50 Go/s, représente moins de 6 % de la bande passante NVLink intra-nœud. C'est pourquoi les stratégies de parallélisme placent systématiquement les communications les plus fréquentes (tensor parallelism) à l'intérieur d'un nœud, et réservent les communications inter-nœuds aux échanges les moins fréquents (data parallelism, pipeline parallelism).

    Les primitives collectives : ce qui se passe réellement pendant un AllReduce

    Quand N GPU doivent moyenner un tenseur de gradients identique en taille sur chacun, l'opération s'appelle un AllReduce. L'implémentation la plus répandue, le Ring-AllReduce, découpe le tenseur en N segments et fait circuler ces segments sur un anneau logique en deux phases :

    1. Scatter-reduce — chaque GPU envoie un segment à son voisin et reçoit le segment correspondant de son autre voisin, en accumulant la somme au passage. Après N-1 étapes, chaque GPU détient la somme complète d'un segment.
    2. All-gather — les segments complets circulent à nouveau sur l'anneau pendant N-1 étapes supplémentaires, jusqu'à ce que chaque GPU possède le tenseur entier réduit.

    Au total, 2(N-1) étapes de communication sont nécessaires, et chaque GPU émet et reçoit environ 2 fois la taille du tenseur divisée par N. La particularité du Ring-AllReduce est que la bande passante utilisée par GPU ne dépend pas de N : c'est un algorithme optimal en bande passante. Sa limite est la latence, qui croît linéairement avec le nombre de GPU — problématique au-delà de quelques dizaines de participants.

    GPU 0 GPU 1 GPU 2 GPU 3 segment i → voisin de droite, à chaque étape
    Ring-AllReduce sur 4 GPU : 2×(N-1), soit 6 étapes de communication pour réduire puis redistribuer le tenseur complet.

    Pour les configurations à très grand nombre de GPU (centaines à milliers), NCCL bascule sur des algorithmes en arbre (double binary tree), qui réduisent la latence en log(N) au prix d'un usage légèrement moins optimal de la bande passante. NCCL choisit automatiquement l'algorithme et le protocole (Simple, LL, LL128) selon la taille du message et la topologie détectée — un comportement observable via NCCL_DEBUG=INFO.

    NCCL en pratique

    NCCL (NVIDIA Collective Communications Library) est la couche qui implémente ces collectives (AllReduce, BroadcastbroadcastRéseauxEnvoi d'une trame à toutes les machines d'un même réseau local simultanément. C'est le mécanisme employé par ARP ou DHCP quand le destinataire n'est pas encore connu.Voir dans le glossaire, AllGather, ReduceScatter, Send/Recv point-à-point) en exploitant automatiquement NVLink, PCIe P2P et le réseau, sans que le code applicatif ait à connaître la topologie. PyTorch, TensorFlow, Horovod et DeepSpeed s'appuient tous dessus en interne.

    Quelques leviers concrets pour diagnostiquer ou ajuster son comportement :

    • NCCL_DEBUG=INFO — affiche l'algorithme, le protocole et les canaux choisis pour chaque collective ; indispensable en cas de scaling décevant.
    • NCCL_IB_DISABLE=1 — force NCCL à retomber sur TCPTCPRéseauxProtocole de transport qui garantit que les données arrivent complètes, dans l'ordre et sans doublon. Il établit une connexion, numérote chaque segment et retransmet ce qui manque.Voir dans le glossaire/Ethernet si InfiniBand pose problème (diagnostic, pas une solution de production).
    • NCCL_SOCKET_IFNAME — force l'interface réseau utilisée, utile quand plusieurs NIC sont présentes et que NCCL en sélectionne une mal adaptée.
    • NCCL_P2P_LEVEL — contrôle l'usage du peer-to-peer PCIe direct entre GPU proches.
    • NCCL_TOPO_FILE — permet de fournir une description explicite de la topologie quand la détection automatique échoue (fréquent sur certaines VM cloud virtualisées).

    Avant de suspecter un bug applicatif face à un scaling décevant, lancez un job avec NCCL_DEBUG=INFO et cherchez la ligne indiquant l'algorithme retenu. Un AllReduce qui bascule sur le protocole réseau le plus lent alors que les GPU sont censés partager un NVSwitch révèle presque toujours un problème de détection de topologie ou de driver, pas un problème de modèle.

    Distributed Data Parallel avec PyTorch

    DDP (torch.nn.parallel.DistributedDataParallel) est le mode de parallélisme de données par défaut de PyTorch. Chaque processus possède une copie complète du modèle sur un GPU dédié, traite un sous-lot différent, calcule son forward et son backward indépendamment, puis synchronise les gradients par AllReduce avant l'étape d'optimiseur. Le point clé : cette synchronisation n'attend pas la fin complète du backward. Des hooks se déclenchent dès qu'un groupe de paramètres (« bucket ») a fini d'accumuler son gradient, ce qui permet de recouvrir la communication par le calcul restant du backward.

    import torch.distributed as dist
    from torch.nn.parallel import DistributedDataParallel as DDP
    
    dist.init_process_group(backend="nccl")
    model = MyModel().to(local_rank)
    model = DDP(model, device_ids=[local_rank])
    # lancement : torchrun --nproc_per_node=8 train.py
    

    La taille des buckets (bucket_cap_mb, 25 Mo par défaut) détermine le recouvrement communication/calcul. Des buckets trop petits multiplient les lancements de collectives et augmentent l'overhead fixe par appel ; des buckets trop grands retardent le déclenchement de l'AllReduce et réduisent le recouvrement. Sur des modèles aux couches très hétérogènes en taille, ajuster ce paramètre peut faire gagner plusieurs points d'efficacité de scaling sans toucher au modèle.

    DDP suppose que chaque GPU peut contenir une copie complète du modèle, de ses gradients et de l'état de l'optimiseur. Pour les modèles qui dépassent cette contrainte, il faut changer de stratégie.

    Sharding pour l'entraînement et l'inférence à grande échelle

    Trois familles de sharding répondent à la limite mémoire de DDP :

    • Tensor parallelism — chaque couche (typiquement les projections linéaires des blocs attentionattentionIAMécanisme par lequel un modèle pondère l'importance de chaque token du contexte lorsqu'il en traite un autre, quelle que soit la distance qui les sépare.Voir dans le glossaire et MLP) est découpée entre GPU, qui calculent chacun une portion de la couche et se synchronisent par AllReduce ou AllGather à chaque couche. Le volume de communication est élevé et fréquent : cette stratégie n'est viable qu'à l'intérieur d'un nœud, sur liens NVLink.
    • Pipeline parallelism — les couches du modèle sont réparties en segments séquentiels sur des GPU différents ; les activations transitent d'un segment à l'autre. Moins gourmand en bande passante que le tensor parallelism, mais introduit une « bulle » d'inactivité pendant le remplissage et la vidange du pipeline, qui pénalise l'efficacité si le micro-batch est trop petit ou le nombre d'étages trop élevé.
    • ZeRO / FSDP (Fully Sharded Data Parallel) — au lieu de dupliquer l'état de l'optimiseur, les gradients et les paramètres sur chaque GPU, ZeRO les partitionne. Stage 1 partitionne l'état de l'optimiseur, stage 2 ajoute les gradients, stage 3 ajoute les paramètres eux-mêmes, reconstitués par AllGather juste avant chaque utilisation puis relâchés. Le gain mémoire est considérable, au prix d'un volume de communication supérieur à DDP classique.

    Un modèle de 70 milliards de paramètres en précisionprécisionIAProportion des alertes émises par un modèle qui sont justifiées. Elle s'oppose au rappel : améliorer l'une dégrade l'autre.Voir dans le glossaire mixte représente environ 140 Go rien que pour les poids, avant gradients et état Adam (qui double ou triple ce volume). Aucun GPU actuel ne loge cela seul. Une configuration réaliste combine tensor parallelism à 4 ou 8 voies à l'intérieur du nœud (liens NVLink), pipeline parallelism entre nœuds, et ZeRO stage 1 ou 2 pour l'état de l'optimiseur — plutôt qu'une seule stratégie appliquée uniformément.

    Pour l'inférenceinférenceIAUtilisation d'un modèle déjà entraîné sur une donnée nouvelle. Peu coûteuse à l'unité mais répétée à chaque requête, elle constitue le coût récurrent d'exploitation.Voir dans le glossaire pure, le sharding privilégié diffère : le tensor parallelism reste pertinent pour réduire la latence par requête sur de très gros modèles, mais on lui préfère souvent des découpages plus simples (pipeline entre nœuds, ou réplication complète du modèle sur des GPU indépendants) quand la métrique visée est le débit global plutôt que la latence d'une requête unique.

    Pourquoi le scaling casse : l'arithmétique de la rentabilité

    L'efficacité de scaling peut se résumer par un ratio simple : temps de calcul divisé par (temps de calcul + temps de communication non recouvert). Ajouter des GPU réduit le temps de calcul par GPU, mais le volume de communication ne diminue pas dans les mêmes proportions — il dépend de la taille du modèle, pas du nombre de GPU. Mécaniquement, la part relative de la communication augmente à mesure que le nombre de GPU croît, jusqu'à ce que l'ajout d'une carte supplémentaire n'apporte plus qu'un gain marginal.

    Quelques repères observés en pratique :

    • Sur un nœud unique avec NVSwitch, une efficacité de scaling de 85 à 95 % jusqu'à 8 GPU est courante pour des modèles suffisamment grands (le calcul par GPU domine largement la communication).
    • Passer à plusieurs nœuds fait typiquement chuter cette efficacité de 10 à 30 points supplémentaires, selon la bande passante réseau disponible et le recouvrement effectif calcul/communication.
    • Pour de petits modèles ou de petits batchs, le temps de calcul par GPU devient trop court pour recouvrir la latence des collectives : au-delà d'un certain nombre de GPU, le temps d'époque peut cesser de diminuer, voire augmenter.

    Ce phénomène n'est pas spécifique à NCCL ou à PyTorch : c'est une conséquence directe de la loi d'Amdahl appliquée à la fraction non parallélisable d'un job — ici, la synchronisation. Aucune optimisation logicielle ne fait disparaître cette borne, elle ne fait que la repousser.

    En pratique, cela signifie qu'un budget GPU doublé ne réduit pas nécessairement le temps d'entraînement de moitié, et que la question pertinente n'est pas « combien de GPU puis-je me payer » mais « à partir de combien de GPU le gain marginal ne couvre-t-il plus le coût marginal ». Mesurer l'efficacité de scaling réel (temps observé vs. temps théorique en scaling linéaire) sur un run court avant d'engager un budget de calcul important évite des semaines de calcul sous-optimal.

    Checklist avant d'investir dans le multi-GPU

    • Le modèle et le batch sont-ils assez gros pour que le calcul par GPU domine largement la communication au nombre de GPU visé ?
    • La topologie réelle de la machine ou de l'instance cloud a-t-elle été vérifiée (nvidia-smi topo -m), pas seulement supposée à partir de la fiche produit ?
    • Le sharding choisi (tensor, pipeline, ZeRO) est-il aligné avec la topologie — communications fréquentes sur NVLink, communications rares entre nœuds ?
    • Un test de scaling court (2, 4, 8 GPU) a-t-il été mesuré avant de réserver la configuration cible ?
    • Le gain de temps attendu justifie-t-il le surcoût, une fois l'efficacité de scaling réelle prise en compte plutôt qu'un scaling linéaire supposé ?
    • Une alternative mono-GPU avec quantification, gradient checkpointing ou offloading CPU a-t-elle été chiffrée comme point de comparaison ?

    L'essentiel à retenir

    Ce chapitre explique pourquoi la topologie physique — PCIe, NVLink, NVSwitch, réseau inter-nœuds — plafonne les gains du multi-GPU avant même d'écrire une ligne de code. Il détaille le fonctionnement des collectives de communication (Ring-AllReduce, arbres) implémentées par NCCL, leur intégration dans PyTorch DDP, et les stratégies de sharding (tensor parallelism, pipeline parallelism, ZeRO/FSDP) pour l'entraînement et l'inférence à grande échelle. Il se termine par une lecture chiffrée des inefficacités de scaling et une checklist pour décider si un investissement multi-GPU est réellement justifié.

    Questions fréquentes

    Faut-il toujours du NVLink pour faire du multi-GPU ?
    Non, DDP fonctionne aussi sur PCIe pur, mais l'efficacité de scaling s'en ressent dès que le volume de gradients à synchroniser devient important par rapport au temps de calcul. Sur PCIe seul, le multi-GPU reste rentable pour des modèles suffisamment gros, mais le point où le scaling casse arrive plus tôt qu'avec NVLink.
    Quelle est la différence concrète entre data parallelism et tensor parallelism ?
    En data parallelism (DDP), chaque GPU a une copie complète du modèle et traite des données différentes ; on synchronise les gradients. En tensor parallelism, le modèle lui-même est découpé entre GPU, qui traitent les mêmes données mais chacun une portion des calculs d'une couche ; on synchronise des activations ou résultats partiels à chaque couche, beaucoup plus fréquemment.
    Comment savoir si mon entraînement multi-GPU est bien scalé ?
    Comparez le temps d'époque mesuré à N GPU avec le temps mesuré à 1 GPU divisé par N. Le ratio (temps théorique idéal / temps réel) donne l'efficacité de scaling. En dessous de 70 %, il vaut la peine d'investiguer la topologie, la taille des buckets DDP, ou la stratégie de sharding avant d'ajouter des GPU supplémentaires.
    NCCL fonctionne-t-il entre GPU de fournisseurs cloud différents ou de générations différentes ?
    NCCL fonctionne avec des GPU NVIDIA hétérogènes en génération, mais les performances s'alignent sur le GPU le plus lent du groupe, et les gains de topologie (NVLink, NVSwitch) ne s'appliquent qu'entre GPU physiquement reliés ainsi. Mélanger des instances de fournisseurs cloud différents implique une communication réseau pour toutes les collectives, avec une latence et une bande passante bien inférieures à une topologie intra-datacenter homogène.
    Le pipeline parallelism vaut-il le coup pour mon cas ?
    Il devient pertinent quand le modèle ne tient pas sur un seul GPU même après tensor parallelism intra-nœud, typiquement au-delà de plusieurs dizaines de milliards de paramètres. Pour des modèles plus petits, la bulle d'inactivité du pipeline (temps de remplissage/vidange) coûte souvent plus qu'elle ne rapporte face à un ZeRO stage 2 ou 3 bien réglé.
    Comment déboguer un blocage (hang) NCCL qui bloque tout le job sans message d'erreur clair ?
    Activez NCCL_DEBUG=INFO et NCCL_DEBUG_SUBSYS=ALL pour localiser le rang et la collective en cause. Les causes les plus fréquentes sont une divergence entre processus (un rang appelle une collective que les autres n'appellent pas, souvent à cause d'un branchement conditionnel asymétrique dans le code), un firewall bloquant le port utilisé par NCCL, ou une carte réseau mal détectée nécessitant NCCL_SOCKET_IFNAME.
    Le multi-GPU peut-il coûter plus cher qu'il ne rapporte ?
    Oui, dès que l'efficacité de scaling réelle chute suffisamment pour que le coût horaire supplémentaire des GPU dépasse le gain de temps obtenu. C'est fréquent avec de petits modèles, des batchs trop petits pour recouvrir la latence des collectives, ou une topologie réseau inter-nœuds insuffisante. Mesurer un run court avant d'engager un budget de calcul important permet d'éviter ce piège.

    Progression sauvegardée dans votre navigateur.

    Quiz de validation

    Quiz de validation

    Quiz indisponible (données invalides).

    Vos projets IA sont-ils sécurisés ? Audit LLM, conformité AI Act, red teaming — devis sous 48h.
    Devis gratuit
    Ch. 8/12 Multi-GPU et NCCL 66% ~30 min Mode lecture v2.7.9