Vous êtes dans un entretien pour un poste d'ingénieur ML chez Google. Interviewer : Nous devons entraîner un LLM sur 1 000 GPU. Comment vous assureriez-vous que tous les GPU partagent ce qu'ils apprennent ? Vous : Utilisez un serveur de paramètres central pour agréger et redistribuer les poids. Entretien terminé. Voici ce que vous avez manqué :
Un goulot d'étranglement majeur en temps d'exécution lors de l'entraînement multi-GPU se produit pendant la synchronisation des GPU. Par exemple, dans l'entraînement multi-GPU via le parallélisme des données : - Le même modèle est distribué à différents GPU. - Chaque GPU traite un sous-ensemble différent de l'ensemble de données complet. Vérifiez cela 👇
Cela entraîne des gradients différents sur différents appareils. Donc, avant de mettre à jour les paramètres du modèle sur chaque appareil GPU, nous devons communiquer les gradients à tous les autres appareils pour les synchroniser. Comprenons maintenant 2 stratégies courantes !
Algorithme 1) All-reduce Une façon évidente est d'envoyer les gradients d'un appareil à tous les autres appareils pour les synchroniser. Mais cela utilise une bande passante élevée. Si chaque GPU a "N" éléments et qu'il y a "G" GPUs, cela entraîne un transfert total de G*(G-1)*N éléments 👇
Nous pouvons optimiser cela en transférant tous les éléments vers un seul GPU, en calculant la valeur finale et en la renvoyant à tous les autres GPU. C'est une amélioration significative. Mais maintenant, un seul GPU doit recevoir, calculer et communiquer les gradients, donc cela ne s'échelonne pas.
Algorithme 2) Réduction en anneau Phase #1) Réduction de partage Tout d'abord, les gradients sont divisés en G segments sur chaque GPU (G = nombre total de GPU). Vérifiez ceci 👇
Lors d'une itération, chaque GPU envoie un segment au GPU suivant : - Le GPU1 envoie a₁ au GPU2, où il est ajouté à b₁ - Le GPU2 envoie b₂ au GPU3, où il est ajouté à c₂ - Le GPU3 envoie c₃ au GPU4, où il est ajouté à d₃ - Le GPU4 envoie d₄ au GPU1, où il est ajouté à a₄ Vérifiez ceci 👇
Ce processus est effectué à nouveau : - GPU1 envoie (d₄+a₄) à GPU2, où il est ajouté à b₄. - GPU2 envoie (a₁+b₁) à GPU3, où il est ajouté à c₁. - GPU3 envoie (b₂+c₂) à GPU4, où il est ajouté à d₂. - GPU4 envoie (c₃+d₃) à GPU1, où il est ajouté à a₃. Vérifiez ceci 👇
Dans la dernière itération, les segments suivants sont transférés au GPU suivant. Cela conduit à un état où chaque GPU a un segment entier, et nous pouvons transférer ces segments complets à tous les autres GPU. Vérifiez ceci 👇
Phase #2) Partage uniquement Maintenant que chaque GPU a un segment entier, nous pouvons transférer ces segments complets à tous les autres GPU. Le processus est réalisé de manière similaire à ce que nous avons discuté ci-dessus, donc nous n'entrerons pas dans les détails complets. L'itération 1 est montrée ci-dessous👇
Ensuite, nous effectuons les itérations 2 et 3. Celles-ci sont réalisées de manière similaire à ce que nous avons appris lors de la Phase 1. Vérifiez ceci 👇
Et voilà ! Les poids du modèle ont été synchronisés entre les GPU. Bien que le nombre total d'éléments transférés soit toujours le même que dans l'approche « single-GPU-master », cette approche en anneau est beaucoup plus évolutive car elle ne met pas toute la charge sur un seul GPU. Vérifiez ceci 👇
Par défaut, les modèles d'apprentissage profond n'utilisent qu'un seul GPU pour l'entraînement, même si plusieurs GPU sont disponibles. Une manière idéale d'entraîner des modèles est de répartir la charge de travail d'entraînement sur plusieurs GPU. Le graphique illustre quatre stratégies pour l'entraînement multi-GPU👇
364,8K