Transformers documentation

Méthodes de parallélisme

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.2).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Méthodes de parallélisme

Les configurations multi-GPU sont efficaces pour accélérer l’entraînement et pour charger en mémoire de grands modèles qui ne tiendraient pas sur un seul GPU. Elles reposent sur la parallélisation de la charge de travail entre plusieurs GPU. Il existe plusieurs types de parallélisme, tels que le parallélisme de données, le parallélisme de tenseurs, le parallélisme par pipeline et le parallélisme de modèle. Chaque type de parallélisme répartit la charge de travail différemment, qu’il s’agisse des données ou du modèle.

Ce guide abordera les différentes méthodes de parallélisme, leur combinaison et le choix d'une stratégie adaptée à votre configuration. Pour plus de détails sur l'entraînement distribué, consultez la documentation Accelerate.

Pour un guide complet sur le passage à l'échelle des grands modèles de langage, consultez le Ultrascale Playbook, qui propose des stratégies détaillées et les meilleures pratiques pour l'entraînement à grande échelle.

Stratégie de scalabilité

Utilisez le Model Memory Calculator pour calculer la quantité de mémoire requise par un modèle. Reportez-vous ensuite au tableau ci-dessous pour choisir une stratégie en fonction de votre configuration.

configurationscénariostratégie
nœud unique / multi-GPUtient sur un seul GPUDistributedDataParallel ou ZeRO
ne tient pas sur un seul GPUPipelineParallel, ZeRO ou TensorParallel
la plus grande couche du modèle ne tient pasTensorParallel ou ZeRO
multi-nœud/multi-GPUinterconnexion rapide entre nœuds (NVLink ou NVSwitch)ZeRO ou parallélisme 3D (PipelineParallel, TensorParallel, DataParallel)
connectivité inter-nœuds lenteZeRO ou parallélisme 3D (PipelineParallel, TensorParallel, DataParallel)

Parallélisme de données

Le parallélisme de données répartit uniformément les données sur plusieurs GPU. Chaque GPU conserve une copie du modèle et traite simultanément sa portion de données. À la fin, les résultats de chaque GPU sont synchronisés et combinés.

Le parallélisme de données réduit considérablement le temps d’entraînement en traitant les données en parallèle, et il est extensible au nombre de GPU disponibles. Toutefois, la synchronisation des résultats de chaque GPU peut entraîner un surcoût.

Il existe deux types de parallélisme de données : DataParallel (DP) et DistributedDataParallel (DDP).

DataParallel

DataParallel prend en charge l'entraînement distribué sur une machine unique équipée de plusieurs GPU.

  1. Le GPU par défaut, GPU 0, lit un lot de données et en envoie un mini-lot aux autres GPU.
  2. Un modèle à jour est répliqué depuis GPU 0 vers les autres GPU.
  3. Un passage en avant forward est effectué sur chaque GPU et leurs sorties sont envoyées vers GPU 0 pour calculer la perte.
  4. La perte est distribuée depuis GPU 0 vers les autres GPU pour le passage backward.
  5. Les gradients de chaque GPU sont renvoyés vers GPU 0 et moyennés.

DistributedDataParallel

DistributedDataParallel prend en charge l'entraînement distribué sur plusieurs machines équipées de plusieurs GPU.

  1. Le processus principal réplique le modèle depuis le GPU par défaut, GPU 0, vers chaque GPU.
  2. Chaque GPU traite directement un mini-lot de données.
  3. Les gradients locaux sont moyennés sur tous les GPU pendant le passage backward.

DDP est recommandé car il réduit la surcharge de communication entre les GPU, exploite efficacement chaque GPU et s'étend à plusieurs machines.

Parallélisme de données ZeRO

Zero Redundancy Optimizer est un type de parallélisme de données plus efficace en termes de mémoire. Il améliore considérablement l'efficacité mémoire en partitionnant les paramètres, les gradients et les états de l'optimiseur entre les processus de parallélisme de données afin de réduire la consommation de mémoire. Il existe trois stades ZeRO :

  • L'étape 1 partitionne les états de l'optimiseur
  • L'étape 2 partitionne les états de l'optimiseur et des gradients
  • L'étape 3 partitionne l'optimiseur, les gradients et les paramètres

Parallélisme de modèle

Le parallélisme de modèle répartit un modèle sur plusieurs GPU. Il existe plusieurs façons de découper un modèle, mais la méthode typique consiste à répartir les couches du modèle sur les GPU. Lors du passage forward, le premier GPU traite un lot de données et le transmet au groupe de couches suivant sur le GPU suivant. Pour le passage backward, les données sont renvoyées en arrière, de la couche finale à la couche initiale.

Le parallélisme de modèles est une stratégie utile pour entraîner des modèles trop volumineux pour tenir dans la mémoire d’un seul GPU. Toutefois, l’utilisation des GPU est déséquilibrée, car un seul GPU est actif à la fois. Le transfert des résultats entre les GPU ajoute également un surcoût de communication, ce qui peut devenir un goulot d’étranglement.

Parallélisme par pipeline

Le parallélisme par pipeline est conceptuellement très similaire au parallélisme de modèle, mais il est plus efficace car il réduit la quantité de temps d'inactivité des GPU. Au lieu d'attendre que chaque GPU termine le traitement d'un lot de données, le parallélisme par pipeline crée des micro-lots de données. Dès qu'un micro-lot est terminé, il est transmis au GPU suivant. De cette manière, chaque GPU peut traiter une partie des données de manière concurrente, sans attendre que l'autre GPU ait complètement terminé le traitement d'un mini-lot de données.

Le parallélisme par pipeline présente les mêmes avantages que le parallélisme par modèle, mais il optimise l'utilisation des GPU et réduit le temps d'inactivité. Toutefois, le parallélisme par pipeline peut être plus complexe, car les modèles doivent parfois être réécrits sous forme de séquences de modules nn.Sequential, et il n'est pas possible d'éliminer totalement le temps d'inactivité, car le dernier passage forward doit également attendre la fin du passage backward.

Parallélisme de tenseurs

Le parallélisme de tenseurs répartit les calculs de grands tenseurs sur plusieurs GPU. Les tenseurs sont découpés horizontalement ou verticalement et chaque tranche est traitée par un GPU distinct. Chaque GPU effectue ses calculs sur sa tranche de tenseur et les résultats sont synchronisés à la fin pour reconstruire le résultat final.

Le parallélisme de tenseurs est efficace pour l’entraînement de grands modèles qui ne tiennent pas dans la mémoire d’un seul GPU. Il est également plus rapide et plus efficace, car chaque GPU peut traiter sa portion de tenseur en parallèle, et il peut être combiné avec d’autres méthodes de parallélisme. Comme les autres méthodes de parallélisme, toutefois, le parallélisme de tenseurs ajoute une surcharge de communication entre les GPU.

Reportez-vous au guide Tensor parallelism pour apprendre à l'utiliser pour l'inférence.

Parallélisme hybride

Les méthodes de parallélisme peuvent être combinées pour obtenir des économies de mémoire encore plus importantes et entraîner plus efficacement des modèles comportant des milliards de paramètres.

Parallélisme de données et parallélisme par pipeline

Le parallélisme de données et de pipeline répartit les données sur les GPU et divise chaque mini-lot de données en micro-lots afin de réaliser le parallélisme de pipeline.

Chaque rang parallèle de données traite le processus comme s'il n'y avait qu'un seul GPU au lieu de deux, mais les GPU 0 et 1 peuvent déléguer des micro-lots de données aux GPU 2 et 3 afin de réduire le temps d'inactivité.

Cette approche optimise le traitement parallèle des données en réduisant l'utilisation inoccupée des GPU.

Parallélisme de données ZeRO, parallélisme par pipeline et parallélisme de modèle (parallélisme 3D)

Le parallélisme de données, de pipeline et de modèle se combinent pour former le parallélisme 3D afin d’optimiser l’efficacité mémoire et de calcul.

L'efficacité mémoire est obtenue en répartissant le modèle sur plusieurs GPU et en le divisant en étapes pour créer un pipeline. Cela permet aux GPU de travailler en parallèle sur des micro-lots de données, réduisant ainsi l'utilisation mémoire du modèle, de l'optimiseur et des activations.

L'efficacité de calcul est rendue possible par le parallélisme de données ZeRO, où chaque GPU ne stocke qu'une portion du modèle, de l'optimiseur et des activations. Cela permet une bande passante de communication plus élevée entre les nœuds de parallélisme de données, car la communication peut se produire de manière indépendante ou en parallèle avec les autres étapes du pipeline.

Cette approche est extensible à des modèles extrêmement volumineux, comptant des milliers de milliards de paramètres.

Update on GitHub