nouvelles

Du bare metal au grand modèle avec 70 milliards de paramètres, voici un tutoriel et des scripts prêts à l'emploi

2024-07-24

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina



Sélectionné sur imbue.com

Auteur : Équipe Imbue

Compilation de coeurs de machines

Editeur : Panda

Nous savons que le LLM est formé sur des clusters informatiques à grande échelle utilisant des données massives. Machine Heart a introduit de nombreuses méthodes et technologies pour assister et améliorer le processus de formation LLM. Aujourd'hui, ce que nous souhaitons partager est un article qui approfondit la technologie sous-jacente et présente comment transformer un groupe de « bare metals » qui n'ont même pas de système d'exploitation en un cluster informatique pour la formation LLM.

Cet article provient d'Imbue, une startup d'IA qui s'efforce d'atteindre une intelligence générale en comprenant comment les machines pensent.

Bien sûr, transformer un tas de « bare metal » sans système d'exploitation en un cluster informatique pour la formation LLM n'est pas un processus facile, plein d'exploration et d'essais et d'erreurs, mais Imbue a finalement réussi à former un LLM avec 70 milliards de paramètres et accumulés. de nombreuses expériences utiles dans le processus.

Cet article fournira une introduction approfondie à l'ensemble du processus de création par l'équipe de sa propre infrastructure de formation LLM et partagera les nombreux outils et scripts qu'ils ont écrits pour faciliter la surveillance, l'inspection et la correction des erreurs.

Si vous souhaitez créer votre propre infrastructure de formation LLM ou si vous êtes curieux de savoir comment est créé le LLM, cet article mérite d'être lu et collecté.

Ce qui suit est le texte original de l'article de l'équipe Imbue.

introduction

Notre petite équipe de chercheurs et d'ingénieurs a passé plusieurs mois à former un modèle de 70 milliards de paramètres à partir de zéro sur notre propre infrastructure, et le modèle a surpassé les modèles zéro-shot sur les tâches liées à l'inférence GPT-4o.

Aujourd'hui, nous partageons le processus de mise en place de l'infrastructure requise : depuis la constitution du cluster initial et l'installation du système d'exploitation jusqu'à la configuration de la récupération automatique lorsque des erreurs sont rencontrées lors de la formation. Nous détaillons les défis rencontrés et les solutions à chaque étape. En plus de ces apprentissages, nous publierons également de nombreux scripts que nous avons développés au fil du temps pour permettre aux autres équipes de créer plus facilement une infrastructure stable pour leur propre formation de modèles.

Tout au long du processus, notre équipe d'ingénieurs a travaillé avec Voltage Park pour préparer les clusters d'ordinateurs et jeter les bases des applications de production. L'ensemble de ce processus comprend :

1. Configurez chaque machine

2. Configurez InfiniBand

3. Assurez-vous que la machine est complètement saine

4. Diagnostiquer les problèmes de formation courants

5. Améliorer les outils d'infrastructure

Chaque étape est décrite en détail ci-dessous.

Contexte : comment il a été fabriqué

Notre objectif en effectuant des calculs est d’assurer une expérimentation rapide avec de grands modèles de langage. Pour ce faire, nous avons besoin d’un grand nombre de GPU à haut débit et d’une communication à haut débit entre ces GPU.

Cet article se concentrera sur un cluster contenant 4088 GPU H100 répartis sur 511 ordinateurs, soit 8 GPU par ordinateur. La raison pour laquelle il existe 511 ordinateurs équipés de GPU est que certaines connexions doivent être réservées au nœud Unified Fabric Manager, dont le rôle est de gérer le réseau InfiniBand. Sur les hôtes équipés de 511 GPU, chaque GPU est directement connecté à une carte réseau ConnectX-7, qui peut transmettre des données à 400 Gbit/s à n'importe quel GPU du réseau InfiniBand.

Notre topologie de réseau InfiniBand est « totalement non bloquante » ; en théorie, cela permet aux GPU de communiquer entre eux à une vitesse maximale. Pour ce faire, nous utilisons une architecture réseau InfiniBand à trois couches : des commutateurs InfiniBand à trois couches. Avec les bonnes connexions, ce niveau élevé de débit peut être atteint sur l’ensemble du réseau. La figure suivante montre un aperçu de ce réseau InfiniBand :



Notez que la communication lors de la formation du réseau s'effectue via InfiniBand et non via Ethernet. Bien que ces machines soient également connectées à Ethernet, le rôle de ce réseau est de transporter des données telles que des jeux de données et des points de contrôle. Si vous utilisez Ethernet pour envoyer des données, la vitesse sera beaucoup plus lente car les données voyageront d'abord du GPU vers le CPU, puis via la carte Ethernet à vitesse de 100 Gbit/s. Bien qu'il soit également possible de s'entraîner sur Ethernet en utilisant une technologie appelée RDMA over Converged Ethernet (RoCE), cela nécessite beaucoup de travail supplémentaire tant du côté matériel que logiciel, et est généralement moins fiable qu'InfiniBand. Pour plus de détails, veuillez vous référer à cet article : https://arxiv.org/pdf/2402.15627

Il existe également un Ethernet secondaire utilisé uniquement pour la configuration et la gestion, donnant accès au BIOS (Basic Input Output System), à l'alimentation et à d'autres interfaces de contrôle pour les interfaces machine de bas niveau. Sans ce réseau de gestion, nous devrions configurer manuellement chaque nœud via un pilote USB, un clavier et un moniteur. Pour les situations comportant des centaines de machines, cette approche n’est pas durable.

Pour réaliser une formation hautes performances sur ce cluster, chaque composant (InfiniBand, Ethernet, GPU et les nœuds eux-mêmes) doit fonctionner presque parfaitement. Si l’une de ces plus de 12 000 connexions est un peu instable, cela peut ralentir le déroulement global de la formation.

Le reste de cet article explique comment faire en sorte que tout fonctionne parfaitement et de manière stable.

Processus : Comment transformer le bare metal en un cluster entièrement opérationnel

Configurer chaque machine

Après avoir établi la connexion Ethernet initiale au cluster via le réseau de gestion, les informations d'identification d'accès au contrôleur de gestion de la carte mère (BMC) sont obtenues. Un BMC est un processeur de service dédié qui surveille à distance les systèmes hôtes et est généralement connecté à un réseau distinct. Il nous permet d'utiliser la machine comme si nous y étions en personne et fournit en outre des API pour l'état du matériel, les paramètres du BIOS et la gestion de l'alimentation.

Une fois ces composants en place, nous pouvons retrousser nos manches et commencer à mettre en place le cluster.

Étape 0 : Configurez d'abord une machine

Nous avons commencé par installer Ubuntu 22.04 sur un serveur utilisant iDRAC (Dell's Baseboard Management Controller), puis avons configuré tout le reste basé sur ce système d'exploitation. L'une des fonctionnalités d'iDRAC est de permettre l'installation et le démarrage d'images ISO à partir de l'ordinateur local et de fournir une console virtuelle via le navigateur. Idéalement, il s’agit de la seule étape d’installation manuelle du processus.

Étape 1 : Installer le système d'exploitation sur chaque machine

Après avoir configuré la première machine, procédez à l'installation du logiciel Metal-as-a-Service (MAAS) d'Ubuntu pour vous aider à configurer les serveurs restants. L'outil de démarrage et d'automatisation iDRAC utilise le protocole PXE (Preboot Execution Environment Protocol) pour demander à chaque machine de démarrer à partir du réseau et de configurer MAAS pour répondre aux demandes de démarrage PXE. Lors d'un démarrage réseau initial, le serveur obtient une adresse IP et un noyau initial de MAAS via le protocole d'allocation IP dynamique DHCP sans avoir à installer quoi que ce soit sur le disque local. Il s'agit de l'environnement de base pour automatiser les installations reproductibles du système d'exploitation. Théoriquement, il suffit d'attendre le premier démarrage et tout sera réglé. Mais en pratique, l'intégration de MAAS avec BMC n'est pas fiable, nous utilisons donc l'API iDRAC pour collecter au préalable l'adresse MAC de chaque machine (un identifiant matériel physique unique).

Tout au long de ce processus de formation, le MAAS est souvent le composant le plus fiable de la pile vertébrale. Cependant, nous avons rencontré au début certains problèmes propres à notre configuration. Par exemple, lors de la configuration des premières machines, je n'ai pas pu installer quoi que ce soit via apt en raison de problèmes de vérification du certificat HTTPS car les horloges étaient très différentes. De même, puisque le serveur MAAS doit être responsable de beaucoup de choses (serveur DHCP, serveur DNS pour résoudre les noms d'hôte en IP, proxy HTTP entre l'hôte et le serveur de packages Ubuntu officiel, serveur NTP, gestion de la configuration cloud-init, un terrain base de données de vérité utilisée pour connecter l'adresse MAC à l'IP, au nom d'hôte et aux métadonnées personnalisées), il nous est donc difficile de résoudre ces problèmes à la racine. De plus, il y a le problème de la courbe d'apprentissage du cycle de vie de la configuration MAAS, car l'objectif de conception est de gérer la complexité de la gestion des déploiements inédits et de la migration progressive des nœuds et de divers états intermédiaires de débogage/malsains.

Étape 2 : diagnostiquer la machine en panne

Nous avons constaté qu'environ 10 % des machines ne parvenaient pas à démarrer, principalement en raison de problèmes physiques avec le serveur. Il s'agit d'un scénario courant pour la configuration de grands clusters GPU. Les situations que nous avons rencontrées incluent : des câbles réseau manquants ou incorrects, des problèmes matériels dans l'iDRAC, des blocs d'alimentation endommagés, des pilotes NVME (mémoire non volatile rapide) endommagés, des lignes internes manquantes, des cartes réseau ou des GPU qui ne s'affichent pas. Nous avons automatiquement vérifié ces problèmes, renvoyé certaines machines à Dell pour les tester à nouveau et soumis les bons de travail appropriés au personnel du centre de données. Un avantage de configurer nous-mêmes le cluster est que nous pouvons immédiatement utiliser des machines saines en attendant la maintenance sur certaines machines.

Étape 3 : Machine observable minimale viable

Nous continuons avec les paramètres suivants sur chaque serveur :

1.Docker (pour faciliter l'exécution des services et des tâches de formation)

2. Pilote GPU du centre de données

3. Outil d'exportation de nœud Prometheus (utilisé pour exporter le flux de données stable des indicateurs de matériel/système d'exploitation)

4. Outil d'exportation DCGM (utilisé pour exporter des données d'indicateurs supplémentaires du GPU NVIDIA, telles que l'état du GPU, l'horloge, l'utilisation)

5. Pool RAIDZ ZFS pour tous les pilotes non liés au système d'exploitation, qui permet à la machine de continuer à fonctionner même en cas de panne d'un pilote, tout en fournissant également une compression transparente gratuite (ceci est particulièrement utile pour les ensembles de données en texte brut et les journaux répétitifs - relativement l'outil augmente généralement l'espace utilisable jusqu'à 10 fois par rapport à la non-utilisation de cet outil)

Nous exécutons ensuite des diagnostics de base du GPU pour déterminer si le GPU fonctionne généralement correctement. Tout ce qui ne fonctionne pas entraînera généralement des problèmes matériels en quelques heures.

Pendant ce temps, nous avons rencontré des goulots d'étranglement de bande passante lorsque nous essayions d'installer simultanément des packages sur les 400 nœuds. C'est la première fois que nous recevons des alertes de surchauffe à haute température sur plusieurs composants déployés dans notre centre de données. Ces premiers problèmes de chauffage ont été en grande partie résolus grâce aux mises à jour du micrologiciel.

Étape 4 : Formation GPU à nœud unique

L’étape suivante consiste à s’assurer que chaque machine peut gérer seule de véritables charges de travail GPU. De nombreuses machines sont incapables de le faire, et les problèmes incluent :

Erreurs liées au GPU, qui peuvent généralement être résolues en réinsérant la carte GPU dans l'emplacement pour carte : faites glisser le serveur de 200 livres hors du rack, retirez tous les câbles entre le capot et le GPU, retirez le GPU, réinstallez le GPU, puis rebranchez les câbles et repoussez le serveur dans le rack.

Selon les journaux du serveur Ubuntu, de nombreux câbles entre le GPU et le bus PCIe ou la carte réseau émettaient cette erreur : « largeur limitée : x4 < x16 ». Après avoir mis à jour le micrologiciel du bus de commutation PCIe, nous avons constaté qu'environ un quart des hôtes nécessitaient de réinstaller les câbles PCIe internes - probablement parce que les câbles entre le boîtier et le GPU sont assez fragiles, ce qui signifie qu'à chaque fois qu'une maintenance est effectuée sur le GPU, ces câbles seront être poussé ou retiré.

Il y a eu quelques pannes diverses qui ont également affecté plusieurs hôtes. Dell nous a aidé à résoudre certains problèmes avec une mise à niveau du micrologiciel :

Le lecteur NVMe ne présentait aucun problème mais bloquait toute la machine lorsqu'il était touché.

Les disques durs apparaissent dans un ordre aléatoire sous Linux, ce qui provoque une confusion dans MAAS et entraîne l'installation du système d'exploitation sur le mauvais disque.

La lecture de la température est erronée, ce qui fait que le ventilateur tourne constamment à pleine vitesse. La raison peut être un problème avec le pilote NVIDIA, qui est résolu en rétrogradant la version du pilote.

La mise à l'échelle dynamique du processeur est devenue incontrôlable, limitant les cœurs de travail à 2 GHz.

La communication directe GPU-GPU (GDR ou GPUDirect RDMA Peer Memory Client) ne peut pas être appliquée avec succès.

Configurer InfiniBand

Étape 0 : Installer UFM

L'un des avantages d'InfiniBand est sa conception centralisée, de sorte que l'ensemble du réseau dispose d'un seul cerveau. Par conséquent, nous n’avons besoin de traiter qu’une seule instance des 320 commutateurs réseau dans l’ensemble de la structure du réseau. Notre première tâche consistait à déterminer quel commutateur connectait quelles machines, puis à l'associer au schéma de câblage et à les renommer en fonction de l'emplacement physique du commutateur.

Étape 1 : recâblage

Initialement, UFM était incapable de détecter ces 320 commutateurs, sans parler des hôtes censés être présents dans la structure. Après avoir consulté nos partenaires de centres de données, nous avons confirmé que les commutateurs étaient sous tension et câblés, mais que nous ne parvenions toujours pas à les détecter. Après avoir examiné la liste du câblage réseau, nous avons remarqué que la conception de haut niveau de la structure du réseau était incorrecte : au lieu d'être unifiée, la structure était divisée en huit réseaux déconnectés sans chemin de routage commun. Après le recâblage, nous avons ajouté une étape de vérification pour vérifier que toutes les connexions physiques sont cohérentes avec la nouvelle conception.

Étape 2 : Dix mille alarmes de température (alerte)

Une fois les problèmes de câblage physique résolus, InfiniBand a réussi à établir des connexions à tous les commutateurs InfiniBand de la structure réseau. Cependant, presque tous les ports de commutation ont commencé à signaler des températures excessives, dépassant parfois 70°C, même s'ils ne transmettaient pas de données. Nous avons découvert que le problème provenait de l'espace ouvert entre les commutateurs d'un même rack, ce qui provoquait un retour d'air chaud vers l'avant. Notre partenaire de centre de données nous a aidé à diagnostiquer rapidement le problème et à développer une solution appropriée.

Étape 3 : 1 800 alarmes

De nombreux ports ont également des taux d'erreur élevés ou font des allers-retours entre les états normal et corrompu, ce que l'on appelle le « battement ». Ces problèmes ne surviennent que lorsque les ports sont réellement utilisés. Ils sont donc difficiles à détecter à l'avance car l'ensemble de notre structure est constitué de 10 000 liens hautement redondants. Notre partenaire du centre de données a aidé à nettoyer et à réinstaller les ports d'alarme, et nous avons désactivé les émetteurs-récepteurs d'alarme restants en attendant leur remplacement.

Bien qu'InfiniBand soit résilient aux pannes matérielles, dès qu'environ 10 % de la structure commence à tomber en panne, des fonctionnalités telles que le routage adaptatif ne fonctionnent plus de manière fiable pour tenir compte des pertes occasionnelles de liaison.

Pendant cette période, nous avons mené avec succès une formation multi-nœuds en utilisant 100 à 200 machines. Notre processus est quelque peu improvisé : nous faisons parfois tourner un ensemble aléatoire de nœuds, observons leurs performances, puis essayons d'en faire fonctionner autant que possible. Cette méthode nous permet de trouver un sous-ensemble fiable de la structure du réseau InfiniBand, mais elle est très difficile car à chaque fois nous devons modifier l'ensemble de nœuds utilisés pour la formation, modifiant ainsi le lien InfiniBand par défaut.

Étape 4 : InfiniBand brûle comme un fou

Pour diagnostiquer plus efficacement les problèmes d'InfiniBand, nous avons conçu une charge de travail pour l'ensemble du cluster qui transmet simultanément autant de données que possible via chaque port de la structure. Ceci est différent de l'exécution d'une charge de travail importante et réduite sur l'ensemble du cluster, qui nécessite l'utilisation de NCCL pour optimiser la communication entre les nœuds individuels en utilisant NVLink pour la communication GPU via les emplacements du module serveur PCIe (SXM).

Au lieu de cela, nous avons opté pour une approche par force brute et avons réussi avec facilité. UFM commencera à émettre des alertes lorsque le volume de transfert de données sur la plupart des ports dépassera 97 % de la capacité théorique, et certains commutateurs tomberont temporairement en panne. Chaque port que nous pensions avoir atteint à la fin de la journée était suffisamment robuste, et le reste a été désactivé ou supprimé en attendant des réparations.

Étape 5 : GPUDirect RDMA

Pour permettre la communication GPU sans encourir de surcharge de calcul CPU, nous avons activé une fonctionnalité appelée GPUDirect RDMA, qui permet une communication directe entre les cartes réseau InfiniBand. Cela implique deux étapes clés :

1. Démarrez un module de noyau supplémentaire

2. Assurez-vous que le service de contrôle d'accès PCIe (ACS) est désactivé pour éviter les blocages immédiats (blocages immédiats)

Étape 6 : Développez le serveur « or »

Pour créer un cluster GPU en utilisant le matériel le plus récent, une règle générale consiste à se préparer à une panne d'environ 3 % de vos machines chaque semaine.

Il convient toutefois de noter que toutes les machines n'ont pas une probabilité uniforme de 3 % de panne, mais un petit nombre de machines non traitées rencontrent divers problèmes à plusieurs reprises jusqu'à ce qu'elles soient correctement réparées. Cela met en évidence les avantages d’avoir un grand nombre de machines dans la même structure de réseau. Ainsi, au lieu de simplement trouver des machines aléatoires sur lesquelles exécuter une formation à grande échelle, comme whack-a-mole pour voir ce qui tombe en panne, notre approche consiste à nous concentrer sur la mise à l'échelle de serveurs réputés fiables, les serveurs « en or ».

Étape 7 : Entretien

La maintenance d'InfiniBand implique principalement de répondre aux alarmes UFM, de remplacer les câbles et émetteurs-récepteurs défectueux et, occasionnellement, de diagnostiquer des erreurs plus difficiles (telles que des pannes de commutateur). Il existe généralement deux facteurs qui conduisent à une maintenance à grande échelle :

1. Les mises à jour du micrologiciel, en particulier lorsque seule la moitié du cluster a terminé la mise à jour, peuvent entraîner un état UFM corrompu et nécessiter un redémarrage UFM sur tous les commutateurs InfiniBand.

2. Les boîtiers GPU sont redémarrés massivement en même temps, ce qui peut injecter un grand nombre de mises à jour dans l'état UFM et nécessiter également de redémarrer le service UFM.

Assurez-vous que la machine est complètement saine

En cours de route, nous avons découvert de multiples façons dont des machines individuelles pouvaient mal fonctionner ou ralentir l'entraînement. Beaucoup de ces modes de défaillance ne sont pas immédiatement apparents, c'est pourquoi nous avons écrit un certain nombre de scripts de vérification de l'état pour vérifier si l'hôte était suffisamment sain. Nous avons publié le code ici : https://github.com/imbue-ai/cluster-health

Notez que bon nombre de ces vérifications de l'état sont spécifiques à notre environnement d'exécution et ne sont pas nécessairement liées au matériel sous-jacent, et ne sont pas non plus nécessairement faciles à corriger ou à automatiser. C'était intentionnel : pour atteindre l'objectif global de préparer nos machines à la formation, nous souhaitions un point d'entrée unique capable de répondre simplement par oui ou par non et de résumer un certain nombre de détails précis.

Bilan de santé du GPU

Nous avons vérifié que le nombre de GPU était correct, que la vérification ECC (Error Correction Code) était activée et qu'il n'y avait aucune erreur ECC. Nous avons également vérifié que la topologie NVLink (qui connecte les GPU entre eux) fonctionne sans erreur.

Bilan de santé de l'espace disque

Nous avons vérifié si l'utilisation de l'espace disque de l'hôte dépasse 95 %.

Bilan de santé Docker

Nous avons vérifié que Docker peut exécuter des conteneurs avec le GPU connecté (c'est-à-dire que NVIDIA Container Runtime fonctionne correctement) et que les conteneurs Docker liés à la surveillance/analyse sont activés et disposent des autorisations d'hôte appropriées.

Bilan de santé Dmesg

Nous avons vérifié dmesg pour les erreurs matérielles Xids ou SXid (défauts causés par les GPU NVIDIA ou les commutateurs NVIDIA inter-GPU). Nous lisons également toutes les lignes de journal dmesg pour vérifier qu'elles peuvent toutes être classées dans la liste Lignes de journal communes/attendues.

Bilan de santé iDRAC

Nous avons vérifié les erreurs iDRAC sur la machine, qui ont ignoré les messages d'erreur non fatales. Il s'agit d'une vérification spécifique aux ordinateurs Dell, elle n'est donc pas incluse dans notre code open source.

Vérification de l'état du disque

Nous avons vérifié que zpool est installé, que Docker y est correctement connecté et qu'il peut effectivement y accéder sans bloquer le CPU.

Bilan de santé InfiniBand

Nous avons vérifié si le taux d'erreur d'InfiniBand augmentait et/ou si le micrologiciel du pilote était obsolète.

Bilan de santé Nvlink

Nous avons vérifié les erreurs NVLink sur la machine. En pratique, cela ne semble pas provoquer d’échecs de formation, mais cela peut ralentir la formation.

Bilan de santé de la RDA

Nous avons vérifié si GDR est activé sur la machine.

Bilan de santé du VBIOS

Nous avons vérifié que la version VBIOS du GPU et le firmware de la carte mère H100 étaient à jour.

Bilan de santé du silex

Nous avons utilisé Flint et hca_self_test pour vérifier que le pilote Mellanox OFED, le micrologiciel de la carte réseau et le micrologiciel de l'émetteur-récepteur étaient des versions correctes et qu'ils étaient correctement compilés pour le pilote NVIDIA.

Bilan de santé du PSB

Nous avons interrogé les périphériques PCIe pour vérifier si la vitesse et la largeur de connexion entre le GPU, le PSB (PCIe Switch Bus) et la carte réseau correspondaient à nos attentes. Nous avons également vérifié que le firmware du switch est à jour. Ce script a été développé par Dell et non par Imbue, nous ne pouvons donc pas le partager pour le moment.

En plus de ces contrôles de santé rapides, nous effectuons également des contrôles de santé plus complexes, notamment :

Initialisez les calculs matriciels via PyTorch et mesurez la bande passante NVLink, la vitesse de calcul et la mémoire du GPU. Nous définissons les indicateurs GDR appropriés pour tester InfiniBand et NVLink.

Utilisez ib_write_bw et –use_cuda pour envoyer des données via la carte IB et mesurer la bande passante des cartes PCIe et InfiniBand. Ce processus a duré longtemps (environ 15 minutes) pour garantir que le lien InfiniBand flottant soit trouvé.

Exécutez une exécution de diagnostic multi-nœuds pour vérifier la capacité d'initialisation de NCCL et si elle se bloque de manière aléatoire. S'il y a des pauses, notre code NCCL fork ajoute une journalisation supplémentaire. Cela prend 12 à 24 heures pour détecter un problème, nous l'exécutons donc généralement uniquement sur de nouveaux nœuds ou lorsque nous soupçonnons un problème.

Vérifiez l'exportation DCGM pour tout événement de limitation d'horloge GPU (à l'exclusion de gpu_idle et power_cap attendus). Pour vérifier ces événements d'alimentation, le meilleur moyen consiste à exécuter une formation multi-nœuds qui vérifie simultanément tous les GPU, cartes InfiniBand, processeurs et disques.

Diagnostiquer les problèmes de formation courants

Une fois le matériel fonctionnel, la formation peut commencer.

Cette section partagera quelques étapes de débogage spécifiques et des informations basées sur notre expérience dans l'exécution de formations de modèles de langage à grande échelle sur notre cluster.

Crash au démarrage

D'une certaine manière, c'est le meilleur bug que vous puissiez rencontrer car il est (théoriquement) facile à reproduire et à itérer.

Nous avons d'abord vérifié que notre code s'exécutait sur la bonne version, la configuration et les variables d'environnement. Bien que basique, nous avons trouvé cela essentiel : garantir que le processus de formation des startups est reproductible et facile à vérifier. L’une des raisons est que les abstractions intermédiaires telles que la mise en cache des images Docker ou les configurations secrètes opaques peuvent prêter à confusion.

Une autre vérification de base que nous effectuons consiste à garantir que toutes les machines sont en ligne et que les traces de pile ou les journaux émis peuvent être facilement regroupés et inspectés. Nous avons utilisé les piles logicielles Loki, Prometheus et Grafana, mais tout outil SaaS d'agrégation de journaux ou de suivi approprié fera l'affaire. Étant donné que ces exécutions de formation sont de nature synchrone et distribuée, la première erreur entraîne souvent une cascade d’erreurs sans rapport. Ici, les contrôles de santé peuvent également aider à détecter immédiatement des erreurs telles qu'un disque dur corrompu ou un GPU manquant ou invalide.

Nous avons construit un système qui redémarre automatiquement en cas de panne, ce qui rend l'agrégation des journaux et des erreurs encore plus importante pour éviter toute confusion entre les erreurs liées aux différents redémarrages. Certaines erreurs courantes que nous rencontrons incluent :

1. Des erreurs telles que « L'ordre direct diffère selon les rangs : le rang 0 rassemble 43 paramètres tandis que le rang 1228 rassemble 1 paramètre ». Nous avons trouvé qu'il s'agissait d'une fonctionnalité étrange de l'implémentation FSDP (Fully Sharded Data Parallel) de PyTorch, qui a été résolue par un redémarrage.

2. Erreur GPU hors mémoire (MOO), qui ressemble à ceci : "CUDA manque de mémoire. J'ai essayé d'allouer..." En vérifiant notre configuration et notre code plusieurs fois et en annulant les modifications récentes du code (en raison de spécifications incorrectes du périphérique PyTorch pendant démarrage et entraînant une utilisation excessive du GPU#0), nous avons résolu ces problèmes.

3. Erreurs CPU/RAM hors mémoire (MOO) Ces erreurs ne sont pas faciles à trouver dans le journal des erreurs et peuvent généralement être détectées via le journal dmesg de l'hôte en dehors du conteneur Docker. Lorsque OOM Killer appelle pour arrêter un processus forké ou un homologue réseau, nous pouvons voir qu'ils se manifestent principalement par CalledProcessError ou ConnectionError. Lorsqu’un appel OOM Killer est détecté depuis dmesg, nous préférons simplement abandonner le bilan de santé et redémarrer la box. Nous avons également vérifié nos chemins de code pour un garbage collection manuel adéquat (il y a une section ci-dessous sur la façon de désactiver cela), et également vérifié toute tentative inattendue d'effectuer des calculs ou de déplacer des tenseurs sur le processeur.

Crash pendant l'entraînement

La première priorité est d'automatiser le système afin qu'il puisse réexécuter automatiquement toutes les vérifications de l'état, puis redémarrer si aucun hôte défectueux n'est trouvé. Nous avons rencontré des erreurs matérielles aléatoires, notamment des erreurs Xid et SXid ; ces erreurs pouvaient provoquer un crash de l'exécution sans émettre de trace de pile Python significative. Certains problèmes, tels que le remappage des lignes, peuvent être résolus en redémarrant. D'autres problèmes, tels que des erreurs ECC non corrigibles, nécessitent souvent une maintenance matérielle ou des pièces de rechange.

De plus, nous avons observé que des données d’entraînement mal formées peuvent également provoquer des plantages. Par exemple, s'il y a un seul document très volumineux dans le corpus, cela peut provoquer une erreur de mémoire insuffisante sur le GPU ou le CPU. Pour éviter ce problème, nous utilisons un chargeur de données entièrement déterministe - rendant chaque crash facilement reproductible en étant lié à une époque ou à un numéro d'étape. Nous avons constaté que la désactivation du chargement des données ou le remplacement de fausses données (telles que des données entièrement nulles) permettent de confirmer si la cause première de l'erreur réside dans les données.

Enfin, il peut également être utile d’enregistrer des statistiques générales sur l’état du réseau et des nœuds via des méthodes d’agrégation de métriques. Des problèmes tels qu'une brève déconnexion Ethernet ou un espace disque faible peuvent ne pas apparaître comme des messages d'erreur utiles, mais peuvent être facilement corrélés aux données collectées.

Se bloquer sans trace de pile (peut avoir des problèmes de délai d'attente plus tard)

En raison du manque d’informations utiles sur ces problèmes et de la difficulté de les reproduire de manière fiable, le débogage de ces types d’erreurs peut s’avérer frustrant.

L'un des types d'erreurs les plus mémorables est accompagné de messages d'erreur comme celui-ci :

Le chien de garde a détecté un dépassement de délai d'opération collective : WorkNCCL (SeqNum=408951, OpType=_ALLGATHER_BASE, … , Timeout (ms)=600000) a été exécuté pendant 600351 millisecondes avant d'expirer

Et tous les travailleurs du GPU participant à la formation ont émis de tels messages d'erreur.

Cela signifie qu'un ou plusieurs hôtes n'ont pas réussi à terminer l'opération NCCL ou que les connexions NCCL et InfiniBand se sont interrompues, provoquant le blocage de tous les autres hôtes sur une opération tensorielle en même temps jusqu'à ce que le délai d'expiration NCCL_TIMEOUT soit atteint. Malheureusement, en raison de la nature de la bibliothèque logicielle NCCL, il est difficile de trouver quel hôte pose problème.

Nous avons apporté quelques modifications à la journalisation de la bibliothèque logicielle NCCL, voir notre version forkée : https://github.com/boweiliu/nccl. Cela peut mieux révéler les messages ou les opérations en cours lorsqu'un crash se produit, et ainsi déterminer quel hôte ou GPU peut l'empêcher de s'exécuter.

Notez que pour identifier les hôtes qui se comportent mal, nous devons souvent déterminer quels hôtes ne génèrent pas certains messages de journal. L'absence de tels messages indique que le travailleur sur cet hôte a pris du retard ou s'est écrasé.

D'autres situations sans réponse sans message d'erreur disponible sont généralement liées à des problèmes liés au matériel, tels que les erreurs Xid/SXid/ECC mentionnées précédemment qui provoquent le verrouillage du pilote NVIDIA ou du pilote de communication NVIDIA Docker. Pour distinguer les blocages NCCL des blocages de pilotes et des conditions de concurrence ou blocages dans le code Python, nous utilisons des outils tels que Py-Spy et le débogueur de projet GNU (GDB) pour déboguer les processus bloqués rencontrés en temps réel. Un problème spécifique a été découvert en utilisant cette approche : en raison d'une erreur de configuration dans les paramètres du thread Python, nous n'avons pas pu lancer correctement huit processus GPU NCCL multithread sur certains hôtes, qui ont rencontré une condition de concurrence critique lors de l'étape du code d'initialisation avant PyTorch.

Ralentissement de l'entraînement (mesuré par MFU)

Le manque d’outils rend ce type de problème encore plus frustrant que le précédent. En plus d'utiliser Py-Spy, l'inspection de trace de pile et GDB, nous avons également utilisé NVIDIA Nsight et des outils de profilage, dont certains sont difficiles à utiliser dans des environnements hautement distribués.

Malheureusement, il existe de nombreuses raisons pour un ralentissement général ou une vitesse inférieure à celle du modèle d'utilisation en virgule flottante (MFU) démontré précédemment.

Premièrement, il s’avère utile de vérifier plusieurs fois les variables de configuration, de code et d’environnement. Les erreurs que nous avons rencontrées incluent l'exécution d'un modèle incorrect, une taille de lot incorrecte, des paramètres UFM ou NCCL incorrects et des erreurs CUDA_DEVICE_MAX_CONNECTIONS. Cela entraînera des performances sous-optimales.

Nous trouvons également utile de mesurer le MFU instantané (c'est-à-dire par lot) (plutôt que les moyennes lissées ou fenêtrées), car les courbes MFU non lissées aident souvent à diagnostiquer les classes problématiques. Les problèmes qui ralentissent la formation comprennent :

Commencez l'entraînement immédiatement à partir d'un MFU très faible (moins d'un dixième de celui attendu) et restez stable

Il s'agit très probablement d'un problème matériel lié à la connexion réseau InfiniBand, tel qu'une panne de commutateur de couche T2 ou T3. Des problèmes matériels entre le GPU et la carte réseau peuvent également provoquer cette situation, pour laquelle dmesg signalera une erreur comme celle-ci : Voies PCIe x16 limitées par…

Commencez l'entraînement immédiatement à partir de 30 % du MFU attendu et maintenez-le stable

Cela peut être dû à des paramètres GDR incorrects sur un hôte (mémoire homologue NVIDIA) ou à des variables d'environnement GDR incorrectes.

Commencez immédiatement l'entraînement à partir d'environ 60 à 80 % du MFU attendu et maintenez-le stable.

La cause la plus courante est une qualité de liaison InfiniBand médiocre ou défectueuse, en particulier une défaillance liée à la carte réseau InfiniBand sur un seul GPU, obligeant NCCL à tenter d'acheminer le trafic via NVLink natif et à utiliser la carte réseau sur un autre GPU sur le même hôte. La limitation du processeur peut également être à l'origine de ce problème, qui nécessite d'ajuster les paramètres du BIOS sur certains hôtes.

Ralentissement soudain et énorme (x 10) lors du traitement de certains lots de données, et cela arrive assez souvent

Il s’agit essentiellement de points de contrôle ou d’évaluation – cela peut être vérifié en vérifiant le nombre d’époques ou d’étapes. Malheureusement, si vous configurez une alarme automatique lorsque le MFU est anormal, de nombreuses fausses alarmes apparaîtront.

Ralentissement soudain et important (chute 10x) lors du traitement de certains lots de données

Cela se produit de manière aléatoire et assez rarement (environ une fois toutes les 15 minutes) et est immédiatement suivi d'un retour complet à un bon MFU.

La cause la plus courante semble être que d'autres charges de travail gourmandes en CPU sont planifiées sur un hôte en cours d'exécution. Nous avons constaté que plutôt que de créer des outils de profilage pour identifier des hôtes spécifiques, il était plus facile de surveiller grossièrement le processeur par PID. La cause peut être des problèmes occasionnels de connectivité réseau, tels que des goulots d'étranglement du chargeur de données. Nous avons surveillé les charges de données, les points de contrôle et les métriques pour tout code non NCCL et ajouté des journaux de synchronisation du code Python, qui se sont révélés très fiables.

MFU ralentit progressivement pendant le fonctionnement, mais revient à 100 % après chaque redémarrage

Théoriquement, la cause pourrait être une accumulation de chaleur sur l’interrupteur, mais nous n’avons jamais vu cela se produire. Cependant, nous avons utilisé les profileurs Python et NVIDIA pour déterminer que la cause de la dégradation des performances semble être le garbage collection automatique.



Lors du débogage de ces ralentissements, nous avons constaté que le débit était presque voué à chuter périodiquement. À mesure que la formation progresse, ce déclin aura un impact croissant sur l’informatique distribuée. Cela nous a amené à soupçonner que la cause de la chute pourrait être liée au garbage collection automatique - une conjecture que nous avons vérifiée par des analyses et des tests. Lorsque nous avons désactivé le garbage collection automatique et défini le garbage collection uniquement à des intervalles spécifiques sur tous les hôtes, cette « baisse » de débit a disparu.

Nous avons utilisé un algorithme de formation distribué synchrone FSDP basé sur ZeRO-3. Lors d'une opération de blocage, un seul processus de travail exécutant le garbage collection peut ralentir tous les autres travailleurs. Si vous disposez de centaines de processus de travail, cela peut entraîner des ralentissements importants.

Les performances sont bonnes au début, puis chutent brusquement (à 70 % de celles attendues) et se poursuivent à haute fréquence (toutes les 15 secondes)

Nous avons observé que cela était lié aux « raisons de limitation d'horloge » sur les GPU NVIDIA, qui peuvent être résolues avec des paramètres appropriés pour NVIDIA DCGM. Des problèmes thermiques (température élevée du GPU ou panne du ventilateur de refroidissement de l'hôte/efficacité réduite) ou une panne d'alimentation peuvent être à l'origine de ce problème. De plus, lorsque nous maximisons l'utilisation des 8 GPU et de l'utilisation de 8x NIC InfiniBand ainsi que du CPU/RAM/disque, certains de nos hôtes dotés d'un matériel d'alimentation spécifique ont des problèmes de tension, mais ne les utilisent tous que (généralement uniquement sur Cela ne se produit que pendant le entraînement réel).

Bonnes performances mais plus de bruit que d'habitude (variation du bruit blanc haute fréquence entre 90 % et 100 % du MFU attendu)

Ceci est également lié au matériel InfiniBand, mais est généralement dû à un certain degré de dégradation des performances ou de gigue sur les liaisons situées plus haut dans le réseau, plutôt qu'aux hôtes les moins redondants de la couche T2.

Malheureusement, bon nombre de ces problèmes sont difficiles à identifier sur un hôte spécifique, et les problèmes liés à InfiniBand sont particulièrement difficiles à identifier en raison de la nature sensible à la topologie de la technologie de commutation InfiniBand. InfiniBand semble favoriser les hôtes adjacents dans la conception InfiniBand fat-tree, tandis que UFM peut acheminer les paquets à des vitesses de liaison asymétriques.

Ce qui suit est une simple liste de contrôle de résumé/organigramme/exhaustivité pour le débogage des problèmes de débit :

Ce système fonctionnait-il correctement auparavant ?

Quelles modifications avez-vous apportées récemment (telles que la fusion du code, la mise à jour des pilotes) ?

L'hôte que vous utilisez est-il en bonne santé ? Tous vos services dépendants fonctionnent-ils normalement, y compris les SaaS tiers, tels que Docker Hub, GitHub, etc. ?

Pouvez-vous être sûr que le code, l'environnement, la configuration, la version, la liste d'hôtes, l'ordre de classement et la graine aléatoire que vous exécutez actuellement sont exactement les mêmes que la dernière fois ? (Si un tel contrôle pouvait être mis en œuvre.)

Le problème est-il reproductible ?

Quel est le rapport avec d’autres choses ? D'autres procédés ? Tâches planifiées crontab quotidiennes ? Hôte ou indicateur DCGM ou UFM ?

Votre outil mesure-t-il correctement ces métriques ?

Le problème persiste-t-il lors de l'exécution d'une version allégée du code (en utilisant des modèles plus petits, de fausses données, aucun point de contrôle de sauvegarde ou de chargement) ?

Améliorer les outils d’infrastructure

Une fois que vous aurez terminé les étapes ci-dessus, vous serez sur la bonne voie pour obtenir de bonnes performances lors de l'entraînement de votre modèle... au moins jusqu'à ce que quelque chose se brise.

Cette section présente certains des outils et systèmes utilisés pour garantir une formation cohérente, tout en nécessitant idéalement le moins d'intervention humaine possible. Comme nous sommes une petite équipe, nous n’avons pas assez de main d’œuvre pour effectuer des réparations manuelles, nous souhaitons donc également automatiser ce processus autant que possible.

Presque tous les problèmes que nous rencontrons lors de la formation peuvent être attribués à une panne de machine ou de composant réseau. Ces types de pannes sont courants dans les grands clusters. Notre approche consiste donc à désactiver automatiquement la machine et les composants réseau défaillants et à envoyer une demande de réparation.

dysfonctionnement de la machine

Nous avons développé un système qui redémarre automatiquement à partir du point de contrôle le plus récent en cas de crash d'une exécution. Dans ce processus de redémarrage, l'état de chaque machine disponible est d'abord vérifié, puis chaque machine est classée en fonction des résultats du contrôle d'état qu'elle réussit, puis une tentative est effectuée pour redémarrer l'entraînement sur la machine la plus saine ;

Défaillance d'un composant réseau

Toutes les pannes de réseau que nous avons observées ont été détectées par UFM et enregistrées dans le journal des événements UFM. La réponse était donc simple : analyser le journal UFM et prendre les mesures appropriées.

Le système d'événements UFM est très complexe et contient des dizaines de types d'événements. En pratique, cependant, nous avons constaté que seuls quelques événements posaient problème, principalement liés à des défaillances de liaison ou à des techniques d’erreur de symboles élevés. Après avoir identifié ces événements, nous pouvons écrire des scripts pour analyser le journal des événements UFM, désactiver les liens et les ports liés aux événements récents, demander des ordres de travail de maintenance pour ces composants réseau et réactiver ces composants une fois la maintenance terminée.

système de fichiers miroir local

Pour ces formations distribuées à grande échelle, on a découvert depuis longtemps que la vitesse d'échange de données entre le cluster et Ethernet constitue un goulot d'étranglement. La bande passante d'une connexion Ethernet partagée est d'environ 10 Gbit/s ; cette bande passante peut devenir rapidement saturée si des centaines de travailleurs téléchargent simultanément des ensembles de données et modélisent des points de contrôle.

À cette fin, nous avons décidé de créer un système de fichiers local au sein de notre cluster comme miroir pour le stockage cloud, qui est essentiellement un espace de cache pouvant réduire la quantité de fichiers lus à partir de S3. Pour tenir compte du désabonnement du cluster (c'est-à-dire lorsqu'une machine est désactivée ou remplacée pour des raisons de maintenance), nous disposons de trois copies de chaque fichier et utilisons un hachage cohérent pour répartir uniformément la charge afin de maximiser les performances pendant le désabonnement du cluster. Le cluster disposant d'un espace disque limité, nous avons dû développer des outils pour suivre le cycle de vie des fichiers et purger les fichiers qui n'étaient plus utiles.

Registre Docker distribué local

Nous avons utilisé Kraken, un excellent logiciel open source pour transférer des images Docker point à point. Nous n'avons eu quasiment aucun problème avec le logiciel, ce qui nous a assez surpris compte tenu de la complexité de nos tâches et de leur mise en œuvre. Adresse de l'outil : https://github.com/uber/kraken

Divers outils de suivi des performances

Nous avons configuré l'analyseur Torch par défaut et les systèmes Nsight de NVIDIA. Ce dernier nous aide à comprendre le temps exact requis pour les passages avant/arrière et la communication NCCL, et nous aide en outre à déterminer si une taille de modèle et un nombre de travailleurs donnés deviendront un goulot d'étranglement. Cependant, Nsight Systems est un peu difficile à utiliser car il nécessite d'exécuter Docker en mode privilégié, ce qui nécessite de désactiver les contrôles de sécurité liés aux événements de surveillance des performances, et la sauvegarde de sa configuration nécessite souvent l'arrêt de l'ensemble du processus de formation.

De plus, nous avons écrit des outils pour détecter les lots de formation lents et comprendre leurs causes possibles. Nous avons trouvé cela utile. L'outil le plus utile surveille la durée de chaque lot et supprime la trace de pile du travailleur si un lot est trop lent, ce qui facilite la recherche d'hôtes présentant des problèmes matériels ou logiciels mineurs.

Divisez les machines en différents groupes pour localiser les hôtes défaillants

Au cours des premiers mois d'utilisation du cluster (lorsque les contrôles de santé n'étaient pas aussi approfondis qu'aujourd'hui), nous avons souvent rencontré une situation où une panne se produisait lors de l'entraînement sur un groupe de machines, mais il n'était pas clair quelle machine posait le problème. . question. Pour trouver les hôtes défectueux, nous avons développé des outils qui permettent de diviser facilement un ensemble de machines en différents groupes et d'exécuter des formations plus petites sur chaque groupe de machines.

Par exemple, si une exécution de formation sur 48 machines échoue, exécutez une exécution de formation plus petite sur 6 groupes de 8 machines chacun, puis exécutez la formation plus petite sur 8 groupes de 6 machines chacun. En règle générale, une seule exécution des deux phases échouera, ce qui nous permet de conclure en toute confiance qu'une machine qui échoue dans les deux phases est défectueuse.

Réflexion et enseignements tirés

Au cours du processus de mise en place et d’entretien de l’infrastructure, nous avons tiré quelques leçons utiles :

Une approche utile consiste à échanger l’emplacement des machines. Au moment de l'exécution, il peut être utile d'utiliser 10 à 20 % de machines en plus que nécessaire afin que la formation puisse être facilement redémarrée en cas de panne de la machine. La configuration d'un réseau de clusters afin que chaque machine soit étroitement connectée à toutes les autres machines nous permet d'utiliser n'importe quel sous-ensemble fonctionnel de ces machines.

Il est utile d'écrire des tests et des solutions automatisées pour chaque panne matérielle ou logicielle que vous rencontrez, car chaque problème rencontré lors de la formation se reproduira. De même, pour chaque message d'erreur ambigu, cela vaut la peine d'écrire un outil qui explique mieux l'erreur.

La reproductibilité est la clé d’une bonne recherche scientifique. L'un des grands principes que nous avons adoptés d'emblée était : « Ne changez qu'une chose à la fois », même dans les choses les plus simples.

Faites confiance, mais vérifiez aussi. Chaque fois que nous faisons appel à des outils externes ou à de nouvelles personnes (que ce soit à l'intérieur ou à l'extérieur de l'entreprise), nous vérifions ce qu'ils prétendent, surtout si les étapes ultérieures dépendent de ces affirmations.

Résumer

La formation de grands modèles de langage nécessite dès le départ une infrastructure complexe. Nous avons choisi de nous impliquer profondément dans les détails de la mise en place de l'infrastructure parce que nous pensons qu'il est important de bien comprendre les systèmes que nous exploitons et parce que nous pensons qu'il est plus efficace de le faire.

Maintenant, après avoir suivi ce processus, nous sommes heureux d'avoir adopté cette approche : avoir un contrôle total sur notre infrastructure et la capacité de déboguer facilement à chaque niveau d'abstraction s'est avéré être d'une valeur cruciale. Bien que ce processus ait nécessité beaucoup de supervision et d'itérations, il nous a permis d'acquérir une compréhension approfondie du flux de travail sous-jacent, de créer un ensemble d'outils pour garantir la santé de l'hôte, d'apprendre à automatiser le système pour garantir une formation continue et fluide et, finalement, de créer un Ensemble d'infrastructures qui nous permettent de former rapidement et de manière itérative des modèles linguistiques de pointe.

Ce processus de construction d'infrastructure reflète notre méthodologie de base pour rechercher et créer des agents d'IA : explorer les détails, améliorer continuellement les processus existants et créer des outils et des systèmes utiles pour permettre à notre équipe motivée de relever des défis plus importants.