notizia

Dal bare metal a un modello di grandi dimensioni con 70 miliardi di parametri, ecco un tutorial e script pronti all'uso

2024-07-24

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



Selezionato da imbue.com

Autore: Imbue Team

Compilazione del cuore della macchina

Redattore: panda

Sappiamo che LLM viene formato su cluster di computer su larga scala utilizzando enormi quantità di dati. Machine Heart ha introdotto molti metodi e tecnologie per assistere e migliorare il processo di formazione LLM. Oggi, ciò che vogliamo condividere è un articolo che approfondisce la tecnologia di base e introduce come trasformare un gruppo di "bare metals" che non dispongono nemmeno di un sistema operativo in un cluster di computer per l'addestramento LLM.

Questo articolo proviene da Imbue, una startup di intelligenza artificiale che si sforza di raggiungere l'intelligenza generale comprendendo come pensano le macchine.

Naturalmente, trasformare un gruppo di "bare metal" senza sistema operativo in un cluster di computer per l'addestramento di LLM non è un processo facile, pieno di esplorazioni, tentativi ed errori, ma Imbue ha finalmente addestrato con successo un LLM con 70 miliardi di parametri e accumulati molte esperienze utili nel processo.

Questo articolo fornirà un'introduzione approfondita all'intero processo di creazione della propria infrastruttura di formazione LLM da parte del team e condividerà i numerosi strumenti e script scritti per facilitare il monitoraggio, l'ispezione e la correzione degli errori.

Se sei interessato a costruire la tua infrastruttura di formazione LLM o sei curioso di sapere come è realizzato LLM, allora vale la pena leggere e collezionare questo articolo.

Quello che segue è il testo originale dell'articolo del team Imbue.

introduzione

Il nostro piccolo team di ricercatori e ingegneri ha trascorso diversi mesi ad addestrare da zero un modello da 70 miliardi di parametri sulla nostra infrastruttura e il modello ha sovraperformato i modelli zero-shot nelle attività relative all’inferenza.

Oggi condividiamo il processo di configurazione dell'infrastruttura richiesta: dalla creazione del cluster iniziale e l'installazione del sistema operativo alla configurazione del ripristino automatico quando si verificano errori durante l'addestramento. Descriviamo in dettaglio le sfide incontrate e le soluzioni in ogni fase. Oltre a questi insegnamenti, rilasceremo anche molti degli script che abbiamo sviluppato lungo il percorso per rendere più semplice per altri team la creazione di un'infrastruttura stabile per il proprio modello di formazione.

Durante tutto il processo, il nostro team di ingegneri ha collaborato con Voltaggio Park per preparare i cluster di computer e costruire le basi per le applicazioni di produzione. L'intero processo include:

1. Configurare ciascuna macchina

2. Configura InfiniBand

3. Assicurarsi che la macchina sia completamente sana

4. Diagnosticare i problemi di formazione più comuni

5. Migliorare gli strumenti infrastrutturali

Ogni passaggio è descritto in dettaglio di seguito.

Background: come è stato realizzato

Il nostro obiettivo nell'esecuzione dei calcoli è garantire una rapida sperimentazione con modelli linguistici di grandi dimensioni. Per fare ciò, abbiamo bisogno di un gran numero di GPU ad alta velocità e di una comunicazione ad alta velocità tra queste GPU.

Questo articolo si concentrerà su un cluster contenente 4088 GPU H100 distribuite su 511 computer o 8 GPU per computer. Il motivo per cui ci sono 511 computer con GPU è perché alcune connessioni devono essere riservate al nodo Unified Fabric Manager, il cui ruolo è gestire la rete InfiniBand. Sugli host 511 dotati di GPU, ciascuna GPU è direttamente connessa a una scheda di rete ConnectX-7, che può trasmettere dati a 400 Gbps a qualsiasi GPU sulla rete InfiniBand.

La nostra topologia di rete InfiniBand è in teoria "completamente non bloccante", ciò consente alle GPU di comunicare tra loro alla massima velocità; Per fare ciò, utilizziamo un'architettura di rete InfiniBand a tre strati: switch InfiniBand a tre strati. Con le giuste connessioni, questo elevato livello di throughput può essere raggiunto su tutta la rete. La figura seguente mostra una panoramica di questa rete InfiniBand:



Tieni presente che la comunicazione durante l'addestramento della rete avviene tramite InfiniBand, non Ethernet. Sebbene queste macchine siano collegate anche a Ethernet, il ruolo di questa rete è quello di trasportare dati come set di dati e checkpoint. Se utilizzi Ethernet per inviare dati, la velocità sarà molto più lenta perché i dati viaggeranno prima dalla GPU alla CPU e poi attraverso la scheda Ethernet con velocità di 100 Gbps. Sebbene sia anche possibile eseguire l'addestramento su Ethernet utilizzando una tecnologia chiamata RDMA over Converged Ethernet (RoCE), che richiede molto lavoro extra sia sul lato hardware che su quello software ed è generalmente meno affidabile di InfiniBand. Per i dettagli, fare riferimento a questo documento: https://arxiv.org/pdf/2402.15627

È inoltre presente una Ethernet secondaria utilizzata solo per la configurazione e la gestione, che fornisce l'accesso al BIOS (Basic Input Output System), all'alimentatore e ad altre interfacce di controllo per le interfacce macchina di basso livello. Senza questa rete di gestione, dovremmo configurare manualmente ciascun nodo tramite un driver USB, una tastiera e un monitor. Per situazioni con centinaia di macchine, questo non è un approccio sostenibile.

Per ottenere un addestramento ad alte prestazioni su questo cluster è necessario che ogni componente (InfiniBand, Ethernet, GPU e i nodi stessi) funzioni quasi perfettamente. Se una qualsiasi di queste oltre 12.000 connessioni è un po’ instabile, ciò può rallentare l’esecuzione complessiva dell’allenamento.

Il resto di questo articolo riguarda come far funzionare tutto perfettamente e stabilmente.

Processo: come trasformare il bare metal in un cluster pienamente operativo

Configura ogni macchina

Dopo aver stabilito la connessione Ethernet iniziale al cluster tramite la rete di gestione, vengono ottenute le credenziali di accesso al controller di gestione del baseboard (BMC). Un BMC è un processore di servizio dedicato che monitora in remoto i sistemi host e solitamente è connesso a una rete separata. Ci consente di utilizzare la macchina come se fossimo lì di persona e fornisce inoltre API per l'integrità dell'hardware, le impostazioni del BIOS e la gestione dell'alimentazione.

Con questi componenti a posto, possiamo rimboccarci le maniche e iniziare a configurare il cluster.

Passaggio 0: configurare prima una macchina

Abbiamo iniziato installando Ubuntu 22.04 su un server utilizzando iDRAC (Baseboard Management Controller di Dell) e quindi configurando tutto il resto in base a questo sistema operativo. Una delle funzionalità di iDRAC è consentire l'installazione e l'avvio di immagini ISO dal computer locale e fornire una console virtuale tramite il browser. Idealmente, questo è l'unico passaggio di installazione manuale nel processo.

Passaggio 1: installare il sistema operativo su ogni macchina

Dopo aver configurato la prima macchina, procedere con l'installazione del software Metal-as-a-Service (MAAS) di Ubuntu per facilitare la configurazione dei server rimanenti. Lo strumento di avvio e automazione iDRAC utilizza Preboot Execution Environment Protocol (PXE) per istruire ogni macchina ad avviarsi dalla rete e configurare MAAS per rispondere alle richieste di avvio PXE. Quando si esegue un avvio di rete iniziale, il server ottiene un IP e un kernel iniziale da MAAS tramite Dynamic IP Allocation Protocol DHCP senza dover installare nulla sull'unità locale. Questo è l'ambiente di base per automatizzare le installazioni ripetibili del sistema operativo. In teoria non ci resta che attendere il primo avvio e tutto sarà sistemato. Ma in pratica, l'integrazione MAAS con BMC è inaffidabile, quindi utilizziamo l'API iDRAC per raccogliere in anticipo l'indirizzo MAC di ciascuna macchina (un identificatore hardware fisico univoco).

Durante l'intero processo di allenamento, il MAAS è spesso il componente più affidabile dello stack vertebrale. Tuttavia, all'inizio abbiamo riscontrato alcuni problemi specifici della nostra configurazione. Ad esempio, durante la configurazione delle prime macchine, non sono riuscito a installare nulla tramite apt a causa di problemi di verifica del certificato HTTPS perché gli orologi erano molto diversi. Allo stesso modo, poiché il server MAAS deve essere responsabile di molte cose (server DHCP, server DNS per la risoluzione dei nomi host in IP, proxy HTTP tra l'host e il server dei pacchetti Ubuntu ufficiale, server NTP, gestione della configurazione cloud-init, un ground database di verità utilizzato per connettere l'indirizzo MAC all'IP, al nome host e ai metadati personalizzati), quindi è difficile per noi risolvere questi problemi dalla causa principale. Inoltre, esiste il problema della curva di apprendimento del ciclo di vita della configurazione MAAS, poiché l'obiettivo della progettazione è gestire la complessità della gestione delle distribuzioni greenfield e la migrazione graduale dei nodi e dei vari stati intermedi di debug/non integri.

Passaggio 2: diagnosticare la macchina rotta

Abbiamo riscontrato che circa il 10% delle macchine non riesce ad avviarsi, principalmente a causa di problemi fisici con il server. Questo è uno scenario comune per la configurazione di cluster GPU di grandi dimensioni. Le situazioni riscontrate includono: cavi di rete mancanti o errati, problemi hardware in iDRAC, alimentatori danneggiati, driver NVME (memoria non volatile veloce) danneggiati, linee interne mancanti, schede di rete o GPU non visualizzate. Abbiamo verificato automaticamente la presenza di questi problemi, restituito alcune macchine a Dell per sottoporle a nuovi test e inviato ordini di lavoro appropriati per il personale del data center. Un vantaggio di configurare da soli il cluster è che possiamo utilizzare immediatamente macchine integre mentre aspettiamo la manutenzione su alcune macchine.

Passo 3: Minimo macchina osservabile vitale

Continuiamo con le seguenti impostazioni su ciascun server:

1.Docker (per semplificare la gestione dei servizi e dei lavori di formazione)

2. Driver GPU del data center

3. Strumento di esportazione del nodo Prometheus (utilizzato per esportare il flusso di dati dell'indicatore hardware/sistema operativo stabile)

4. Strumento di esportazione DCGM (utilizzato per esportare dati indicatori aggiuntivi dalla GPU NVIDIA, come stato della GPU, orologio, utilizzo)

5. Pool RAIDZ ZFS per tutti i driver non del sistema operativo, che consente alla macchina di continuare a funzionare anche se un driver si guasta, fornendo anche una compressione trasparente gratuitamente (questo è particolarmente utile per set di dati di testo normale e registri ripetitivi - relativamente lo strumento in genere aumenta lo spazio utilizzabile fino a 10 volte rispetto al non utilizzo di questo strumento)

Quindi eseguiamo la diagnostica di base della GPU per determinare se la GPU funziona generalmente correttamente: qualsiasi cosa che non lo sia di solito porterà a problemi hardware entro poche ore.

Durante questo periodo, abbiamo riscontrato colli di bottiglia nella larghezza di banda durante il tentativo di installare pacchetti su tutti i 400 nodi contemporaneamente. Questa è la prima volta che riceviamo avvisi di surriscaldamento ad alta temperatura su più componenti distribuiti nel nostro data center. Questi primi problemi di riscaldamento sono stati in gran parte risolti tramite aggiornamenti del firmware.

Passaggio 4: training GPU a nodo singolo

Il passo successivo è garantire che ogni macchina possa gestire autonomamente i carichi di lavoro reali della GPU. Molte macchine non sono in grado di farlo e i problemi includono:

Errori relativi alla GPU, che generalmente possono essere risolti reinserindo la scheda GPU nello slot per schede: far scorrere il server da 200 libbre fuori dal rack, rimuovere tutti i cavi tra il coperchio e la GPU e rimuovere la GPU, reinstallare la GPU, quindi ricollegare i cavi e reinserire il server nel rack.

Secondo i log del server Ubuntu, molti cavi tra la GPU e il bus PCIe o la scheda di rete hanno emesso questo errore: "larghezza limitata: x4 < x16". Dopo aver aggiornato il firmware dello switch bus PCIe, abbiamo scoperto che circa un quarto degli host necessitava di riposizionare i cavi PCIe interni, presumibilmente perché i cavi tra il case e la GPU sono piuttosto fragili, il che significa che ogni volta che viene eseguita la manutenzione sulla GPU, questi cavi essere spinto o tirato fuori.

Si sono verificate alcune interruzioni varie che hanno interessato anche diversi host. Dell ci ha aiutato a risolvere alcuni problemi con un aggiornamento del firmware:

L'unità NVMe non ha mostrato difetti ma ha bloccato l'intera macchina quando è stata toccata.

I dischi rigidi appaiono in ordine casuale sotto Linux, causando confusione in MAAS e causando l'installazione del sistema operativo sull'unità sbagliata.

La lettura della temperatura è errata, il che fa sì che la ventola funzioni sempre alla massima velocità. Il motivo potrebbe essere un problema con il driver NVIDIA, che viene risolto effettuando il downgrade della versione del driver.

Lo scaling dinamico della CPU è andato fuori controllo, limitando i core funzionanti a 2 GHz.

Impossibile applicare correttamente la comunicazione diretta GPU-GPU (GDR o GPUDirect RDMA Peer Memory Client).

Configura InfiniBand

Passaggio 0: installa UFM

Un vantaggio di InfiniBand è la sua struttura centralizzata, in modo che l'intera rete abbia un solo cervello. Pertanto, dobbiamo occuparci solo di un'istanza dei 320 switch di rete nell'intera struttura di rete. Il nostro primo compito è stato quello di capire quale interruttore collegava quali macchine, quindi associarlo allo schema elettrico e rinominarlo in base alla posizione fisica dell'interruttore.

Passaggio 1: ricablaggio

Inizialmente, UFM non è stata in grado di rilevare quei 320 switch, per non parlare degli host che avrebbero dovuto essere presenti nel fabric. Dopo aver consultato i nostri partner del data center, abbiamo confermato che gli interruttori erano accesi e cablati, ma non eravamo ancora in grado di rilevarli. Dopo aver esaminato l'elenco dei cavi di rete, abbiamo notato che la progettazione di livello superiore della struttura di rete non era corretta: invece di essere unificata, la struttura era divisa in otto reti disconnesse senza percorso di instradamento comune. Dopo il ricablaggio, abbiamo aggiunto una fase di controllo per verificare che tutte le connessioni fisiche siano coerenti con il nuovo design.

Passaggio 2: diecimila allarmi di temperatura (avviso)

Una volta risolti i problemi di cablaggio fisico, InfiniBand ha stabilito con successo le connessioni a tutti gli switch InfiniBand nella struttura di rete. Tuttavia, quasi tutte le porte dello switch hanno iniziato a segnalare temperature eccessive, a volte superiori a 70°C, anche se non stavano trasmettendo dati. Abbiamo scoperto che il problema derivava dallo spazio aperto tra gli switch nello stesso rack, che causava il riflusso dell'aria calda verso la parte anteriore. Il nostro partner del data center ci ha aiutato a diagnosticare rapidamente il problema e a sviluppare una soluzione adeguata.

Passaggio 3: 1800 allarmi

Molte porte hanno anche tassi di errore elevati o vanno avanti e indietro tra lo stato normale e quello danneggiato, fenomeno chiamato "flapping". Questi problemi sorgono solo quando le porte vengono effettivamente utilizzate, quindi sono difficili da individuare in anticipo perché tutta la nostra struttura è composta da 10.000 collegamenti altamente ridondanti. Il nostro partner del data center ci ha aiutato a pulire e reinstallare le porte dell'allarme e abbiamo disabilitato i restanti ricetrasmettitori di allarme mentre aspettavamo la sostituzione.

Sebbene InfiniBand sia resistente ai guasti hardware, una volta che circa il 10% del tessuto inizia a guastarsi, funzionalità come il routing adattivo non funzionano in modo affidabile per tenere conto del collegamento perso occasionale.

Durante questo periodo, abbiamo eseguito con successo la formazione multi-nodo utilizzando da 100 a 200 macchine. Il nostro processo è in qualche modo improvvisato: a volte creiamo un insieme casuale di nodi, osserviamo le loro prestazioni e quindi proviamo a mantenerne in funzione il maggior numero possibile. Questo metodo ci consente di trovare un sottoinsieme affidabile della struttura della rete InfiniBand, ma è molto difficile perché ogni volta dobbiamo modificare l'insieme di nodi utilizzati per l'addestramento, modificando così il collegamento InfiniBand predefinito.

Passaggio 4: InfiniBand brucia come un matto

Per diagnosticare i problemi InfiniBand in modo più efficiente, abbiamo progettato un carico di lavoro per l'intero cluster che spingesse quanti più dati possibile attraverso ogni porta della struttura simultaneamente. Questo è diverso dall'esecuzione di un grande carico di lavoro di riduzione totale sull'intero cluster, che richiede l'utilizzo di NCCL per ottimizzare la comunicazione tra i singoli nodi utilizzando NVLink per la comunicazione GPU tramite gli slot Server PCIe Module (SXM).

Invece, abbiamo optato per un approccio basato sulla forza bruta e ci siamo riusciti con facilità. UFM inizierà a emettere avvisi quando il volume di trasferimento dati sulla maggior parte delle porte supera il 97% della capacità teorica e alcuni switch verranno temporaneamente disattivati. Ogni porta che pensavamo fosse arrivata alla fine della giornata era sufficientemente robusta e le altre sono state disabilitate o rimosse in attesa di riparazioni.

Passaggio 5: RDMA GPUDirect

Per consentire la comunicazione GPU senza incorrere in un sovraccarico di elaborazione della CPU, abbiamo abilitato una funzionalità chiamata GPUDirect RDMA, che consente la comunicazione diretta tra le schede di rete InfiniBand. Ciò comporta due passaggi fondamentali:

1. Avviare un modulo kernel aggiuntivo

2. Assicurarsi che il servizio di controllo dell'accesso PCIe (ACS) sia disabilitato per evitare blocchi immediati (blocco immediato)

Passaggio 6: espandere il server “gold”.

Per creare un cluster GPU utilizzando l'hardware più recente, una regola pratica è quella di essere pronti a far sì che circa il 3% delle macchine si guasti ogni settimana.

Va tuttavia notato che non tutte le macchine hanno una probabilità di guasto uniforme del 3%, ma un piccolo numero di macchine non trattate presenta ripetutamente vari problemi finché non viene adeguatamente riparata. Ciò evidenzia i vantaggi di avere un gran numero di macchine nella stessa struttura di rete. Quindi, invece di trovare semplicemente macchine casuali su cui eseguire corsi di formazione su larga scala, come "colpisci la talpa" per vedere cosa si rompe, il nostro approccio è quello di concentrarsi sulla scalabilità di server noti per essere affidabili, i server "d'oro".

Passaggio 7: manutenzione

La manutenzione di InfiniBand implica principalmente la risposta agli allarmi UFM, la sostituzione di cavi e ricetrasmettitori difettosi e, occasionalmente, la diagnosi di errori più difficili (come guasti agli interruttori). Solitamente sono due i fattori che portano ad una manutenzione su larga scala:

1. Gli aggiornamenti del firmware, soprattutto quando solo la metà del cluster ha completato l'aggiornamento, potrebbero causare uno stato UFM danneggiato e richiedere il riavvio dell'UFM su tutti gli switch InfiniBand.

2. I box GPU vengono riavviati in modo massiccio allo stesso tempo, il che potrebbe inserire un gran numero di aggiornamenti nello stato UFM e richiedere anche il riavvio del servizio UFM.

Assicurarsi che la macchina sia completamente sana

Lungo il percorso, abbiamo scoperto diversi modi in cui le singole macchine potevano funzionare male o rallentare l’allenamento. Molte di queste modalità di errore non sono immediatamente evidenti, quindi abbiamo scritto una serie di script di controllo dello stato per verificare se l'host era sufficientemente integro. Abbiamo pubblicato il codice qui: https://github.com/imbue-ai/cluster-health

Tieni presente che molti di questi controlli di integrità sono specifici del nostro ambiente di runtime e non sono necessariamente correlati all'hardware sottostante, né sono necessariamente facili da correggere o automatizzare. Questo era previsto dalla progettazione: per raggiungere l'obiettivo generale di preparare le nostre macchine per l'allenamento, volevamo un unico punto di ingresso che potesse rispondere a un semplice sì o no e che potesse riassumere un numero qualsiasi di dettagli fini.

Controllo dello stato della GPU

Abbiamo controllato che il numero di GPU fosse corretto, che il controllo ECC (Error Correction Code) fosse abilitato e che non fossero presenti errori ECC. Abbiamo anche controllato che la topologia NVLink (che collega le GPU tra loro) sia attiva e funzionante senza errori.

Controllo dello stato dello spazio su disco

Abbiamo verificato se l'utilizzo dello spazio su disco dell'host supera il 95%.

Controllo dello stato di Docker

Abbiamo verificato che Docker possa eseguire contenitori con la GPU connessa (ovvero, NVIDIA Container Runtime funzioni correttamente) e che i contenitori Docker relativi al monitoraggio/analisi siano attivati ​​e dispongano delle autorizzazioni host corrette.

Controllo dello stato di salute del Dmesg

Abbiamo controllato dmesg per verificare la presenza di errori Xid hardware o SXid (guasti causati da GPU NVIDIA o switch NVIDIA inter-GPU). Leggiamo anche tutte le righe di registro di dmesg per verificare che possano essere tutte classificate nell'elenco Righe di registro comuni/previste.

Controllo dello stato dell'iDRAC

Abbiamo verificato la presenza di errori iDRAC sulla macchina, che hanno ignorato i messaggi di errore non irreversibili. Si tratta di un controllo specifico per i computer Dell, pertanto non è incluso nel nostro codice open source.

Controllo dello stato del disco

Abbiamo verificato che zpool sia installato, che Docker sia correttamente connesso ad esso e che possa effettivamente raggiungerlo senza bloccare la CPU.

Controllo dello stato di InfiniBand

Abbiamo controllato se il tasso di errore di InfiniBand fosse aumentato e/o se il firmware del driver fosse obsoleto.

Controllo dello stato di Nvlink

Abbiamo verificato la presenza di errori NVLink sulla macchina. In pratica, ciò non sembra causare fallimenti nell'addestramento, ma potrebbe rallentarlo.

Controllo sanitario della DDR

Abbiamo controllato se GDR è abilitato sulla macchina.

Controllo dello stato del VBIOS

Abbiamo verificato che la versione VBIOS della GPU e il firmware della scheda base H100 fossero aggiornati.

Controllo sanitario di Flint

Abbiamo utilizzato flint e hca_self_test per verificare che il driver Mellanox OFED, il firmware della scheda di rete e il firmware del ricetrasmettitore fossero delle versioni corrette e che fossero compilati correttamente per il driver NVIDIA.

Controllo sanitario del PSB

Abbiamo interrogato i dispositivi PCIe per verificare se la velocità e l'ampiezza della connessione tra GPU, PSB (PCIe Switch Bus) e scheda di rete erano quelle che ci aspettavamo. Abbiamo anche verificato che il firmware dello switch sia aggiornato. Questo script è stato sviluppato da Dell, non da Imbue, quindi al momento non possiamo condividerlo.

Oltre a questi rapidi controlli sanitari, eseguiamo anche alcuni controlli sanitari più complessi, tra cui:

Inizializza i calcoli della matrice tramite PyTorch e misura la larghezza di banda NVLink, la velocità di calcolo e la memoria della GPU. Impostiamo i flag GDR appropriati per testare InfiniBand e NVLink.

Utilizza ib_write_bw e –use_cuda per inviare dati tramite la scheda IB e misurare la larghezza di banda della scheda PCIe e InfiniBand. Questo processo è durato a lungo (circa 15 minuti) per garantire che il collegamento InfiniBand svolazzante fosse trovato.

Eseguire un'esecuzione diagnostica multinodo per verificare la capacità di inizializzazione dell'NCCL e se si blocca in modo casuale. Se ci sono pause, il nostro codice NCCL biforcato aggiunge ulteriore registrazione. Sono necessarie dalle 12 alle 24 ore per rilevare un problema, quindi in genere lo eseguiamo solo su nuovi nodi o quando sospettiamo un problema.

Controlla l'esportazione DCGM per eventuali eventi di limitazione dell'orologio della GPU (esclusi gpu_idle e power_cap previsti). Per verificare la presenza di questi eventi di alimentazione, il modo migliore è eseguire un training multi-nodo che controlli simultaneamente tutte le GPU, le schede InfiniBand, le CPU e i dischi.

Diagnosticare problemi comuni di formazione

Una volta che l'hardware funziona correttamente, è possibile iniziare la formazione.

Questa sezione condividerà alcuni passaggi e approfondimenti specifici di debug basati sulla nostra esperienza nell'esecuzione di corsi di formazione su modelli linguistici di grandi dimensioni sul nostro cluster.

Crash all'avvio

In un certo senso, questo è il miglior bug che puoi incontrare perché è (teoricamente) facile da riprodurre e da iterare.

Per prima cosa abbiamo verificato che il nostro codice fosse in esecuzione sulla versione, sulla configurazione e sulle variabili di ambiente corrette. Sebbene sia fondamentale, riteniamo che questo sia fondamentale: garantire che il processo di formazione della startup sia riproducibile e facile da controllare. Uno dei motivi è che le astrazioni intermedie come la memorizzazione nella cache delle immagini Docker o le configurazioni segrete opache possono causare confusione.

Un altro controllo di base che eseguiamo è garantire che tutte le macchine siano online e che le tracce dello stack o i log emessi possano essere facilmente aggregati e ispezionati. Abbiamo utilizzato gli stack software Loki, Prometheus e Grafana, ma qualsiasi strumento SaaS di aggregazione di log o di tracciamento adatto andrà bene. Poiché queste esecuzioni di training sono sincrone e distribuite per natura, il primo errore spesso porta a una cascata di errori non correlati. In questo caso, i controlli sanitari possono anche aiutare a rilevare immediatamente errori come un disco rigido danneggiato o una GPU mancante o non valida.

Abbiamo creato un sistema che si riavvia automaticamente in caso di guasto, il che rende l'aggregazione di log ed errori ancora più importante per evitare errori confusi dovuti a diversi riavvii. Alcuni errori comuni che riscontriamo includono:

1. Errori come "L'ordine in avanti differisce tra i ranghi: il rango 0 raccoglie tutti i 43 parametri mentre il rango 1228 raccoglie tutti i 1 parametri". Abbiamo riscontrato che si tratta di una strana funzionalità dell'implementazione Fully Sharded Data Parallel (FSDP) di PyTorch, che è stata risolta con un riavvio.

2. Errore GPU di memoria esaurita (OOM), simile a questo: "CUDA memoria esaurita. Tentativo di allocare..." Controllando la nostra configurazione e il nostro codice più volte e annullando le recenti modifiche al codice (a causa di specifiche errate del dispositivo PyTorch durante avvio e conseguente utilizzo eccessivo della GPU#0), abbiamo risolto questi problemi.

3. Errori di memoria insufficiente CPU/RAM (OOM) Questi errori non sono facili da trovare nel registro degli errori e in genere possono essere rilevati tramite il registro dmesg dell'host all'esterno del contenitore Docker. Quando OOM Killer chiama per interrompere un processo biforcato o un peer di rete, possiamo vedere che si manifestano principalmente come CalledProcessError o ConnectionError. Quando viene rilevata una chiamata OOM Killer da dmesg, preferiamo semplicemente abbandonare il controllo dello stato e riavviare il box. Abbiamo anche controllato i nostri percorsi di codice per un'adeguata garbage collection manuale (c'è una sezione sotto su come disabilitarla) e abbiamo anche controllato eventuali tentativi imprevisti di eseguire calcoli o spostare tensori sulla CPU.

Crash durante l'allenamento

La prima priorità è automatizzare il sistema in modo che possa eseguire nuovamente automaticamente tutti i controlli di integrità e quindi riavviarsi se non viene trovato un host non integro. Abbiamo riscontrato alcuni errori hardware casuali, inclusi errori Xid e SXid, questi errori potrebbero causare l'arresto anomalo dell'esecuzione senza emettere una traccia dello stack Python significativa; Alcuni problemi, come la rimappatura delle righe, possono essere risolti riavviando. Altri problemi, come errori ECC irreversibili, spesso richiedono la manutenzione dell'hardware o la sostituzione di parti.

Inoltre, abbiamo osservato che anche dati di training non corretti possono causare arresti anomali. Ad esempio, se nel corpus è presente un singolo documento molto grande, ciò potrebbe causare un errore di memoria insufficiente sulla GPU o sulla CPU. Per evitare questo problema, utilizziamo un caricatore di dati completamente deterministico, rendendo ogni arresto anomalo facilmente riproducibile essendo legato a un'epoca o a un numero di passaggio. Abbiamo scoperto che disabilitare il caricamento dei dati o sostituire i dati falsi (come i dati tutti zero) aiuta a confermare se la causa principale dell'errore sono i dati.

Infine, può anche essere utile registrare statistiche sullo stato generale della rete e dei nodi tramite metodi di aggregazione metrica. Problemi come una breve disconnessione Ethernet o spazio su disco insufficiente potrebbero non essere visualizzati come messaggi di errore utili, ma possono essere facilmente correlati ai dati raccolti.

Blocca senza traccia dello stack (potrebbero verificarsi problemi di timeout in seguito)

A causa della mancanza di informazioni utili su questi problemi e della difficoltà di riprodurli in modo affidabile, il debug di questi tipi di errori può essere frustrante.

Uno dei tipi di errori più memorabili è accompagnato da messaggi di errore come questo:

Il watchdog ha rilevato un timeout dell'operazione collettiva: WorkNCCL (SeqNum=408951, OpType=_ALLGATHER_BASE, … , Timeout (ms)=600000) è stato eseguito per 600351 millisecondi prima del timeout

E tutti i lavoratori della GPU durante il corso di formazione hanno emesso tali messaggi di errore.

Ciò significa che uno o più host non sono riusciti a completare l'operazione NCCL o che le connessioni NCCL e InfiniBand si sono bloccate, causando il blocco di tutti gli altri host su un'operazione tensore contemporaneamente fino al raggiungimento del timeout NCCL_TIMEOUT. Sfortunatamente, a causa della natura della libreria software NCCL, è difficile individuare quale host presenta il problema.

Abbiamo apportato alcune modifiche alla registrazione della libreria software NCCL, vedere la nostra versione biforcuta: https://github.com/boweiliu/nccl. Ciò potrebbe rivelare meglio i messaggi o le operazioni eseguite quando si verifica un arresto anomalo e quindi determinare quale host o GPU potrebbe impedirne l'esecuzione.

Tieni presente che per identificare gli host che si comportano in modo anomalo, spesso dobbiamo capire quali host non generano determinati messaggi di registro. L'assenza di tali messaggi indica che il lavoratore su questo host è rimasto indietro o si è bloccato.

Altre situazioni di mancata risposta senza messaggi di errore disponibili sono generalmente legate a problemi relativi all'hardware, come gli errori Xid/SXid/ECC menzionati in precedenza che causano il blocco del driver NVIDIA o del driver di comunicazione NVIDIA Docker. Per distinguere i blocchi NCCL dai blocchi dei driver e dalle condizioni di competizione o dai deadlock nel codice Python, utilizziamo strumenti come Py-Spy e GNU Project Debugger (GDB) per eseguire il debug dei processi bloccati incontrati in tempo reale. Utilizzando questo approccio è stato scoperto un problema specifico: a causa di un errore di configurazione nelle impostazioni del thread Python, non siamo stati in grado di avviare correttamente otto processi GPU NCCL multi-thread su alcuni host, che hanno riscontrato una race condition nella fase di inizializzazione del codice prima di PyTorch.

Rallentamento dell'allenamento (misurato dalla MFU)

La mancanza di strumenti rende questo tipo di problema ancora più frustrante del precedente. Oltre a utilizzare Py-Spy, l'ispezione dello stack trace e GDB, abbiamo utilizzato anche NVIDIA Nsight e strumenti di profilazione, alcuni dei quali sono difficili da utilizzare in ambienti altamente distribuiti.

Sfortunatamente, ci sono molte ragioni per un rallentamento generale o una velocità inferiore rispetto al modello di utilizzo in virgola mobile (MFU) dimostrato in precedenza.

Innanzitutto, risulta utile controllare più volte la configurazione, il codice e le variabili di ambiente. Gli errori che abbiamo riscontrato includono l'esecuzione del modello sbagliato, dimensioni batch errate, impostazioni UFM o NCCL errate, errori CUDA_DEVICE_MAX_CONNECTIONS. Ciò si tradurrà in prestazioni non ottimali.

Riteniamo inoltre utile misurare la MFU istantanea (ovvero per lotto) (piuttosto che le medie livellate o finestrate), poiché le curve MFU non livellate spesso aiutano a diagnosticare le classi problematiche. I problemi che rallentano l’allenamento includono:

Iniziare subito ad allenarsi da una MFU molto bassa (meno di un decimo del previsto) e mantenersi stabile

Molto probabilmente si tratta di un problema hardware con la connessione di rete InfiniBand, ad esempio un arresto anomalo dello switch di livello T2 o T3. Anche problemi hardware tra la GPU e la scheda NIC possono causare questa situazione, per la quale dmesg segnalerà un errore come questo: PCIe x16 lanes limited by...

Inizia immediatamente l'allenamento dal 30% della MFU prevista e mantieniti costante

Ciò potrebbe essere causato da impostazioni GDR errate su un host (memoria peer NVIDIA) o variabili di ambiente GDR errate.

Iniziare immediatamente l'allenamento da circa il 60-80% della MFU prevista e mantenersi costanti

La causa più comune è la qualità del collegamento InfiniBand scarsa o difettosa, in particolare un guasto relativo alla scheda NIC InfiniBand su una singola GPU, che induce NCCL a tentare di instradare il traffico tramite NVLink nativo e utilizzare la scheda NIC su un'altra GPU sullo stesso host. Anche la limitazione della CPU può causare questo problema, che richiede la regolazione delle impostazioni del BIOS su alcuni host.

Enorme rallentamento improvviso (di 10 volte) durante l'elaborazione di determinati batch di dati, e questo accade abbastanza spesso

Fondamentalmente si tratta di checkpoint o valutazione: questo può essere verificato controllando il numero di epoche o passaggi. Purtroppo, se si imposta un allarme automatico quando la MFU è anomala, appariranno molti falsi allarmi.

Enorme rallentamento improvviso (calo di 10 volte) durante l'elaborazione di determinati batch di dati

Ciò avviene in modo casuale e abbastanza raro (circa una volta ogni 15 minuti) ed è seguito immediatamente da un ritorno completo a una buona MFU.

La causa più comune sembra essere la pianificazione di altri carichi di lavoro ad uso intensivo della CPU su un host in esecuzione. Abbiamo scoperto che invece di creare strumenti di profilazione per identificare host specifici, era più semplice monitorare approssimativamente la CPU tramite PID. La causa potrebbe essere un problema occasionale di connettività di rete, ad esempio un collo di bottiglia del caricatore di dati. Abbiamo monitorato i caricamenti dei dati, i checkpoint e le metriche per qualsiasi codice non NCCL e abbiamo aggiunto i registri dei tempi del codice Python, che si sono rivelati molto affidabili.

La MFU rallenta gradualmente durante il funzionamento, ma ritorna al 100% dopo ogni riavvio

In teoria, la causa potrebbe essere l'accumulo di calore sull'interruttore, ma non l'abbiamo mai visto accadere. Tuttavia, abbiamo utilizzato i profiler Python e NVIDIA per determinare che la causa del degrado delle prestazioni sembra essere la garbage collection automatica.



Durante il debug di questi rallentamenti, abbiamo scoperto che il throughput era quasi destinato a diminuire periodicamente. Con il progredire della formazione, questo declino avrà un impatto crescente sul calcolo distribuito. Questo ci ha portato a sospettare che la causa del calo possa essere legata alla garbage collection automatica, una congettura che abbiamo verificato attraverso analisi e test. Quando abbiamo disabilitato la garbage collection automatica e impostato la garbage collection solo a intervalli specifici su tutti gli host, questo "calo" di throughput è scomparso.

Abbiamo utilizzato un algoritmo di training distribuito sincrono FSDP basato su ZeRO-3. Durante un'operazione di blocco, un singolo processo di lavoro che esegue la garbage collection può rallentare tutti gli altri lavoratori. Se disponi di centinaia di processi di lavoro, ciò può causare rallentamenti significativi.

Le prestazioni sono inizialmente buone, poi calano improvvisamente (al 70% del previsto) e continuano ad alta frequenza (ogni 15 secondi)

Abbiamo osservato che questo problema è correlato a "motivi di limitazione del clock" sulle GPU NVIDIA, che possono essere risolti con le impostazioni appropriate per NVIDIA DCGM. Problemi termici (temperatura elevata della GPU o guasto della ventola di raffreddamento dell'host/efficacia ridotta) o un guasto dell'alimentatore possono causare questo problema. Inoltre, quando massimizziamo l'utilizzo di tutte le 8 GPU e l'utilizzo di 8x NIC InfiniBand insieme a CPU/RAM/disco, alcuni dei nostri host con hardware di alimentazione specifico presentano problemi di tensione, ma li usano solo tutti (di solito solo su Ciò si verifica solo durante percorso di allenamento vero e proprio).

Buone prestazioni ma più rumore del solito (variazione del rumore bianco ad alta frequenza tra il 90% e il 100% della MFU prevista)

Anche questo è correlato all'hardware InfiniBand, ma in genere è dovuto a un certo grado di degrado delle prestazioni o jitter sui collegamenti più in alto nella rete, piuttosto che sugli host meno ridondanti al livello T2.

Sfortunatamente, molti di questi problemi sono difficili da individuare a un host specifico e i problemi relativi a InfiniBand sono particolarmente difficili da individuare a causa della natura sensibile alla topologia della tecnologia switch InfiniBand. InfiniBand sembra favorire gli host adiacenti nel design ad albero grasso InfiniBand, mentre UFM può instradare i pacchetti a velocità di collegamento asimmetriche.

Quello che segue è un semplice riepilogo/diagramma di flusso/elenco di controllo di completezza per il debug dei problemi di throughput:

Questo sistema funzionava correttamente prima?

Quali modifiche hai apportato di recente (come l'unione del codice, l'aggiornamento dei driver)?

L'host che stai utilizzando è sano? Tutti i servizi dipendenti funzionano normalmente, inclusi SaaS di terze parti, come Docker Hub, GitHub, ecc.?

Puoi essere sicuro che il codice, l'ambiente, la configurazione, la versione, l'elenco degli host, l'ordine di classificazione e il seed casuale che stai eseguendo ora siano esattamente gli stessi dell'ultima volta? (Se tale controllo potesse essere implementato.)

Il problema è riproducibile?

Come si collega ad altre cose? Altri processi? Attività pianificate crontab giornaliere? Indicatore host o DCGM o UFM?

Il tuo strumento misura correttamente queste metriche?

Il problema persiste quando si esegue una versione ridotta del codice (utilizzando modelli più piccoli, dati falsi, nessun salvataggio o caricamento di checkpoint)?

Migliorare gli strumenti infrastrutturali

Una volta completati i passaggi precedenti, sarai sulla buona strada per ottenere buone prestazioni durante l'addestramento del tuo modello... almeno finché qualcosa non si rompe.

Questa sezione introduce alcuni degli strumenti e dei sistemi utilizzati per garantire una formazione coerente, richiedendo idealmente il minor intervento umano possibile. Dato che siamo un team piccolo, non disponiamo di manodopera sufficiente per eseguire riparazioni manuali, quindi vogliamo automatizzare il più possibile anche questo processo.

Quasi tutti i problemi che incontriamo durante la formazione possono essere attribuiti a guasti della macchina o dei componenti di rete. Questi tipi di guasti sono comuni nei cluster di grandi dimensioni, quindi il nostro approccio consiste nel disabilitare automaticamente la macchina e i componenti di rete guasti e inviare una richiesta di riparazione.

malfunzionamento della macchina

Abbiamo sviluppato un sistema che si riavvia automaticamente dal checkpoint più recente se una corsa si arresta in modo anomalo. In questo processo di riavvio, ogni macchina disponibile viene prima sottoposta a controllo di integrità, quindi ogni macchina viene classificata in base ai risultati del controllo di integrità che supera; quindi viene effettuato un tentativo di riavviare l'addestramento sulla macchina più in salute.

Guasto del componente di rete

Tutti gli errori di rete che abbiamo osservato sono stati rilevati da UFM e registrati nel registro eventi UFM, quindi la risposta è stata semplice: analizzare il registro UFM e intraprendere l'azione appropriata.

Il sistema di eventi UFM è molto complesso e contiene decine di tipi di eventi. In pratica, tuttavia, abbiamo riscontrato che solo pochi eventi erano problematici, principalmente legati a guasti dei collegamenti o tecniche con errori elevati nei simboli. Dopo aver identificato questi eventi, possiamo scrivere script per analizzare il registro eventi UFM, disabilitare i collegamenti e le porte relative agli eventi recenti, richiedere ordini di lavoro di manutenzione per questi componenti di rete e riattivare questi componenti al termine della manutenzione.

file system mirror locale

Per questi corsi di formazione distribuiti su larga scala è stato scoperto da tempo che la velocità dello scambio di dati tra il cluster ed Ethernet rappresenta un collo di bottiglia. La larghezza di banda di una connessione Ethernet condivisa è di circa 10 Gbit/s e può saturarsi rapidamente se centinaia di lavoratori scaricano set di dati e modellano checkpoint contemporaneamente.

A tal fine, abbiamo deciso di creare un file system locale all'interno del nostro cluster come mirror per l'archiviazione nel cloud, che è essenzialmente uno spazio cache in grado di ridurre la quantità di file letti da S3. Per tenere conto della varianza del cluster (ovvero, quando una macchina viene disabilitata o sostituita per motivi di manutenzione), abbiamo tre copie di ciascun file e utilizziamo un hashing coerente per distribuire uniformemente il carico per massimizzare le prestazioni durante la varianza del cluster. Poiché il cluster ha uno spazio su disco limitato, abbiamo dovuto sviluppare strumenti per tenere traccia del ciclo di vita dei file ed eliminare quelli che non erano più utili.

Registro Docker distribuito locale

Abbiamo utilizzato Kraken, un ottimo software open source per il trasferimento di immagini Docker punto a punto. Non abbiamo avuto quasi nessun problema con il software, il che per noi è stato piuttosto sorprendente, considerando la complessità dei nostri compiti e della nostra implementazione. Indirizzo dello strumento: https://github.com/uber/kraken

Vari strumenti di monitoraggio delle prestazioni

Abbiamo configurato l'analizzatore Torch predefinito e i sistemi Nsight di NVIDIA. Quest'ultimo ci aiuta a comprendere il tempo esatto richiesto per i passaggi avanti/indietro e la comunicazione NCCL, e inoltre ci aiuta a determinare se una determinata dimensione del modello e un determinato numero di lavoratori diventeranno un collo di bottiglia. Tuttavia, Nsight Systems è un po' difficile da usare perché richiede l'esecuzione di Docker in modalità privilegiata, che richiede la disabilitazione dei controlli di sicurezza relativi agli eventi di monitoraggio delle prestazioni, e il salvataggio della sua configurazione spesso richiede l'interruzione dell'intero processo di formazione.

Inoltre, abbiamo scritto strumenti per rilevare batch di training lenti e comprenderne le possibili cause. Lo abbiamo trovato utile. Lo strumento più utile monitora il tempo impiegato da ciascun batch ed elimina l'analisi dello stack del lavoratore se un batch è troppo lento, semplificando la ricerca di host con problemi hardware o software minori.

Dividere le macchine in diversi gruppi per individuare gli host guasti

Nei primi mesi di utilizzo del cluster (quando i controlli di integrità non erano così approfonditi come lo sono adesso), spesso ci imbattevamo in una situazione in cui si verificava un guasto durante l'addestramento su un gruppo di macchine, ma non era chiaro quale macchina avesse il problema . domanda. Per individuare host difettosi, abbiamo sviluppato strumenti che semplificano la suddivisione di un set di macchine in gruppi diversi e l'esecuzione di corsi di formazione più piccoli su ciascun gruppo di macchine.

Ad esempio, se un allenamento su 48 macchine fallisce, esegui un allenamento più piccolo su 6 gruppi di 8 macchine ciascuno, quindi esegui l'allenamento più piccolo su 8 gruppi di 6 macchine ciascuno. In genere, solo un ciclo delle due fasi fallirà, dandoci la certezza di concludere che una macchina che fallisce in entrambe le fasi è difettosa.

Riflessione e lezioni apprese

Durante il processo di creazione e manutenzione dell’infrastruttura, abbiamo imparato alcune lezioni utili:

Un approccio utile è scambiare la posizione delle macchine. In fase di esecuzione, può essere utile utilizzare il 10-20% di macchine in più del necessario in modo che la formazione possa essere facilmente riavviata in caso di guasto della macchina. La configurazione della rete cluster in modo che ogni macchina sia strettamente connessa a ogni altra macchina ci consente di utilizzare qualsiasi sottoinsieme funzionante di tali macchine.

Vale la pena scrivere test e soluzioni automatizzate per ogni guasto hardware o software riscontrato, perché ogni problema riscontrato durante la formazione si ripresenterà. Allo stesso modo, per ogni messaggio di errore ambiguo, vale la pena scrivere uno strumento che spieghi meglio l'errore.

La riproducibilità è la chiave per una buona ricerca scientifica. Uno dei grandi principi che abbiamo adottato fin da subito è stato: “Cambiare solo una cosa alla volta”, anche nelle cose più semplici.

Abbi fiducia, ma anche verifica. Ogni volta che utilizziamo strumenti esterni o assumiamo nuove persone (dall'interno o dall'esterno dell'azienda), ricontrolliamo ciò che affermano, soprattutto se i passaggi successivi dipendono da tali affermazioni.

Riassumere

La formazione di modelli linguistici di grandi dimensioni richiede fin dall’inizio un’infrastruttura complessa. Abbiamo scelto di essere coinvolti profondamente nei dettagli della realizzazione dell'infrastruttura perché crediamo che sia importante comprendere appieno i sistemi in cui operiamo e perché crediamo che sia più efficiente farlo.

Ora, dopo aver seguito il processo, siamo lieti di aver adottato questo approccio: avere il controllo completo sulla nostra infrastruttura e la capacità di eseguire facilmente il debug a ogni livello di astrazione si è rivelato di valore fondamentale. Anche se questo processo ha richiesto molta supervisione e iterazione, ci ha permesso di acquisire una profonda comprensione del flusso di lavoro sottostante, creare una serie di strumenti per garantire l'integrità dell'host, imparare come automatizzare il sistema per garantire una formazione continua e fluida e, infine, creare un sistema Insieme di infrastrutture che ci consentono di addestrare in modo rapido e iterativo modelli linguistici all'avanguardia.

Questo processo di costruzione dell'infrastruttura riflette la nostra metodologia di base per la ricerca e la creazione di agenti IA: esplorazione dei dettagli, miglioramento continuo dei processi esistenti e creazione di strumenti e sistemi utili per consentire al nostro team motivato di affrontare sfide più grandi.