Parallelismo dei dati partizionati - Amazon SageMaker AI

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Parallelismo dei dati partizionati

Il parallelismo dei dati partizionati è una tecnica di addestramento distribuito a risparmio di memoria che suddivide lo stato di un modello (parametri del modello, gradienti e stati dell'ottimizzatore) tra le GPU in un gruppo parallelo di dati.

Nota

Il parallelismo dei dati partizionati è disponibile per PyTorch nella libreria di parallelismo dei modelli SageMaker v1.11.0 e versioni successive.

Quando aumenta il processo addestramento su un cluster di GPU di grandi dimensioni, è possibile ridurre l'ingombro di memoria della GPU del modello partizionando lo stato di addestramento del modello su più GPU. Ciò offre due vantaggi: è possibile utilizzare modelli più grandi, che altrimenti esaurirebbero la memoria con il parallelismo dei dati standard, oppure è possibile aumentare la dimensione del batch utilizzando la memoria della GPU liberata.

La tecnica standard di parallelismo dei dati replica gli stati di addestramento tra le GPU del gruppo parallelo di dati ed esegue l'aggregazione del gradiente in base all'operazione AllReduce. Il parallelismo dei dati partizionati modifica la procedura di addestramento distribuito standard parallelo ai dati per tenere conto della natura di partizionamento degli stati dell'ottimizzatore. Un gruppo di classificazioni sui cui gli stati del modello e dell'ottimizzatore sono partizionati viene chiamato gruppo di partizione. La tecnica del parallelismo dei dati partizionati suddivide i parametri addestrabili di un modello, i gradienti e gli stati di ottimizzazione corrispondenti tra le GPU del gruppo di partizionamento.

SageMaker AI raggiunge la parallelizzazione dei dati sottoposti a sharding attraverso l’implementazione di MiCS, discusso nel post del blog AWS Near-linear scaling of gigantic-model training on AWS. In questa implementazione, è possibile impostare il grado di partizionamento come parametro configurabile, che deve essere inferiore al grado di parallelismo dei dati. Durante ogni passaggio in avanti e all'indietro, MiCS ricombina temporaneamente i parametri del modello in tutte le GPU tramite l'operazione.AllGather. Dopo il passaggio in avanti o all'indietro di ogni livello, MiCS partiziona nuovamente i parametri per risparmiare memoria della GPU. Durante il passaggio all'indietro, MiCS riduce i gradienti e li partiziona simultaneamente tra le GPU durante l'operazione ReduceScatter. Infine, MiCS applica i gradienti locali ridotti e partizionati alle corrispondenti partizioni di parametri locali, utilizzando le partizioni locali degli stati dell'ottimizzatore. Per ridurre il sovraccarico della comunicazione, la libreria di parallelismo dei modelli SageMaker esegue il pre-fetching dei livelli successivi nel passaggio in avanti o all'indietro e sovrappone la comunicazione di rete al calcolo.

Lo stato di addestramento del modello viene replicato tra i gruppi di partizione. Ciò significa che prima di applicare i gradienti ai parametri, l'operazione AllReduce deve avvenire tra i gruppi di partizione, oltre all'operazione ReduceScatter che avviene all'interno del gruppo di partizione.

In effetti, il parallelismo dei dati partizionati introduce un compromesso tra il sovraccarico delle comunicazioni e l'efficienza della memoria della GPU. L'uso del parallelismo dei dati partizionati aumenta i costi della comunicazione, ma l'ingombro della memoria della GPU (escluso l'utilizzo della memoria dovuto alle attivazioni) viene suddiviso per il grado di parallelismo dei dati partizionati, quindi è possibile inserire modelli più grandi nel cluster della GPU.

Selezione del grado di parallelismo dei dati partizionati

Quando si seleziona un valore per il grado di parallelismo dei dati partizionati, il valore deve dividere equamente il grado di parallelismo dei dati. Ad esempio, per un processo di parallelismo dei dati a 8 vie, scegli 2, 4 o 8 per il grado di parallelismo dei dati partizionati. Nella scelta del grado di parallelismo dei dati partizionati, si consiglia di iniziare con un numero piccolo e di aumentarlo gradualmente fino a quando il modello non si adatta alla memoria con la dimensione del batch desiderata.

Selezione della dimensione del batch

Dopo aver impostato il parallelismo dei dati partizionati, assicurati di trovare la configurazione di addestramento più ottimale che possa essere eseguito correttamente sul cluster GPU. Per addestrare modelli linguistici di grandi dimensioni (LLM), inizia dalla dimensione del batch 1 e aumentala gradualmente fino a raggiungere il punto in cui si verificherà l'errore di esaurimento della memoria (OOM). Se riscontri l'errore OOM anche con la dimensione del batch più piccola, applica un grado più elevato di parallelismo dei dati partizionati o una combinazione di parallelismo dei dati partizionati e parallelismo tensoriale.

Come applicare il parallelismo dei dati partizionati al tuo processo di addestramento

Per iniziare con il parallelismo dei dati partizionati, applica le modifiche necessarie allo script di addestramento e configura lo strumento di valutazione SageMaker PyTorch con i parametri specifici del parallelismo dei dati partizionati. Considera anche di prendere come punto di partenza i valori di riferimento e i notebook di esempio.

Adatta il tuo script di addestramento PyTorch

Segui le istruzioni della Fase 1: modifica uno script di addestramento PyTorch per includere gli oggetti del modello e dell'ottimizzatore con i wrapper smdistributed.modelparallel.torch dei moduli torch.nn.parallel e torch.distributed.

(Facoltativo) Modifica aggiuntiva per registrare i parametri esterni del modello

Se il modello è costruito con torch.nn.Module e utilizza parametri che non sono definiti all'interno della classe del modulo, è necessario registrarli manualmente nel modulo per consentire a SMP di raccogliere i parametri completi. Per registrare i parametri in un modulo, utilizza smp.register_parameter(module, parameter).

class Module(torch.nn.Module): def __init__(self, *args): super().__init__(self, *args) self.layer1 = Layer1() self.layer2 = Layer2() smp.register_parameter(self, self.layer1.weight) def forward(self, input): x = self.layer1(input) # self.layer1.weight is required by self.layer2.forward y = self.layer2(x, self.layer1.weight) return y

Configurare lo strumento di valutazione SageMaker PyTorch

Quando configuri uno strumento di valutazione SageMaker PyTorch in Fase 2: avvio di un processo di addestramento utilizzando SageMaker SDK Python, aggiungi i parametri per il parallelismo dei dati partizionati.

Per attivare il parallelismo dei dati partizionati, aggiungi il parametro sharded_data_parallel_degree allo strumento di valutazione SageMaker PyTorch. Questo parametro specifica il numero di GPU su cui viene partizionato lo stato di addestramento. Il valore di sharded_data_parallel_degree deve essere un numero intero compreso tra uno e il grado di parallelismo dei dati e deve dividere equamente il grado di parallelismo dei dati. Nota che la libreria rileva automaticamente il numero di GPU, quindi il grado di parallelismo dei dati. I seguenti parametri aggiuntivi sono disponibili per configurare il parallelismo dei dati partizionati.

  • "sdp_reduce_bucket_size"(int, default: 5e8): specifica la dimensione dei bucket di gradiente PyTorch DDP in numero di elementi del dtype predefinito.

  • "sdp_param_persistence_threshold"(int, default: 1e6): specifica la dimensione di un tensore di parametri in numero di elementi che possono persistere in ogni GPU. Il parallelismo dei dati partizionati divide i tensori dei parametri tra le GPU di un gruppo parallelo di dati. Se il numero di elementi nel tensore dei parametri è inferiore a questa soglia, il tensore del parametro non viene suddiviso; ciò aiuta a ridurre il sovraccarico di comunicazione perché il tensore dei parametri viene replicato su GPU parallele ai dati.

  • "sdp_max_live_parameters"(int, default: 1e9): specifica il numero massimo di parametri che possono trovarsi contemporaneamente in uno stato di addestramento ricombinato durante il passaggio in avanti e all'indietro. Il recupero dei parametri con l'operazione AllGather si interrompe quando il numero di parametri attivi raggiunge la soglia specificata. Si noti che l'aumento di questo parametro aumenta l'ingombro di memoria.

  • "sdp_hierarchical_allgather"(bool, default: True): se impostato su True, l'operazione AllGatherviene eseguita in modo gerarchico: viene eseguita prima all'interno di ogni nodo e poi tra i nodi. Per i processi di addestramento distribuito su più nodi, l'operazione AllGather gerarchica viene attivata automaticamente.

  • "sdp_gradient_clipping"(float, default: 1.0): specifica una soglia per il ritaglio del gradiente secondo la norma L2 dei gradienti prima di propagarli all'indietro attraverso i parametri del modello. Quando è attivato il parallelismo dei dati partizionati, viene attivato anche il ritaglio del gradiente. La soglia predefinita è 1.0. Regola questo parametro se hai il problema dei gradienti esplosivi.

Il codice seguente mostra un esempio di come configurare il parallelismo dei dati partizionati.

import sagemaker from sagemaker.pytorch import PyTorch smp_options = { "enabled": True, "parameters": { # "pipeline_parallel_degree": 1, # Optional, default is 1 # "tensor_parallel_degree": 1, # Optional, default is 1 "ddp": True, # parameters for sharded data parallelism "sharded_data_parallel_degree": 2, # Add this to activate sharded data parallelism "sdp_reduce_bucket_size": int(5e8), # Optional "sdp_param_persistence_threshold": int(1e6), # Optional "sdp_max_live_parameters": int(1e9), # Optional "sdp_hierarchical_allgather": True, # Optional "sdp_gradient_clipping": 1.0 # Optional } } mpi_options = { "enabled" : True, # Required "processes_per_host" : 8 # Required } smp_estimator = PyTorch( entry_point="your_training_script.py", # Specify your train script role=sagemaker.get_execution_role(), instance_count=1, instance_type='ml.p3.16xlarge', framework_version='1.13.1', py_version='py3', distribution={ "smdistributed": {"modelparallel": smp_options}, "mpi": mpi_options }, base_job_name="sharded-data-parallel-job" ) smp_estimator.fit('s3://my_bucket/my_training_data/')

Configurazioni di riferimento

Il team di addestramento distribuito di SageMaker fornisce le seguenti configurazioni di riferimento che è possibile utilizzare come un punto di inizio. Puoi estrapolare le configurazioni seguenti per sperimentare e stimare l'utilizzo della memoria della GPU per la configurazione del modello.

Parallelismo dei dati partizionati con i collettivi SMDDP

Modello/numero di parametri Numero di istanze Tipo di istanza Lunghezza della sequenza Dimensioni batch globali Dimensioni del mini-batch Grado parallelo di dati partizionati
GPT-NEOX-20B 2 ml.p4d.24xlarge 2048 64 4 16
GPT-NEOX-20B 8 ml.p4d.24xlarge 2048 768 12 32

Ad esempio, se aumenti la lunghezza della sequenza per un modello da 20 miliardi di parametri o aumenti le dimensioni del modello a 65 miliardi di parametri, dovresti prima provare a ridurre la dimensione del batch. Se il modello continua a non adattarsi alla dimensione del batch più piccola (la dimensione del batch pari a 1), prova ad aumentare il grado di parallelismo del modello.

Parallelismo dei dati partizionati con parallelismo tensoriale e collettivi NCCL

Modello/numero di parametri Numero di istanze Tipo di istanza Lunghezza della sequenza Dimensioni batch globali Dimensioni del mini-batch Grado parallelo di dati partizionati Grado di parallelo tensoriale Offload di attivazione
GPT-NEOX-65B 64 ml.p4d.24xlarge 2048 512 8 16 8 Y
GPT-NEOX-65B 64 ml.p4d.24xlarge 4096 512 2 64 2 Y

L'uso combinato del parallelismo dei dati partizionati e del parallelismo tensoriale è utile quando si desidera inserire un modello linguistico di grandi dimensioni (LLM) in un cluster su larga scala utilizzando dati di testo con una lunghezza di sequenza maggiore, il che porta a utilizzare un batch di dimensioni inferiori e, di conseguenza, a gestire l'utilizzo della memoria della GPU per addestrare gli LLM su sequenze di testo più lunghe. Per ulteriori informazioni, consulta Parallelismo dei dati partizionati con parallelismo tensoriale.

Per casi di studio, benchmark e altri esempi di configurazione, consulta il post del blog Nuovi miglioramenti delle prestazioni nella libreria di parallelizzazione dei modelli di Amazon SageMaker AI.

Parallelismo dei dati partizionati con i collettivi SMDDP

La libreria di parallelismo dei dati SageMaker offre primitive di comunicazione collettiva (collettivi SMDDP) ottimizzate per l'infrastruttura AWS. Ottiene l'ottimizzazione adottando un modello di comunicazione completo utilizzando Elastic Fabric Adapter (EFA), con conseguente throughput elevato e collettivi meno sensibili alla latenza, scaricando l'elaborazione relativa alla comunicazione sulla CPU e liberando i cicli della GPU per il calcolo. Su cluster di grandi dimensioni, i collettivi SMDDP possono offrire miglioramenti nelle prestazioni di addestramento distribuito fino al 40% rispetto a NCCL. Per casi di studio e risultati dei benchmark, consulta il blog Nuovi miglioramenti delle prestazioni nella libreria di parallelizzazione dei modelli di Amazon SageMaker AI.

Nota

Il parallelismo dei dati partizionati con le raccolte SMDDP è disponibile nella libreria di parallelismo dei modelli SageMaker v1.13.0 e versioni successive e nella libreria di parallelismo dei dati SageMaker v1.6.0 e versioni successive. Vedi anche Supported configurations per utilizzare il parallelismo dei dati partizionati con i collettivi SMDDP.

Nel parallelismo dei dati partizionati, che è una tecnica comunemente usata nell'addestramento distribuito su larga scala, il collettivo AllGather viene utilizzato per ricostituire i parametri dei livelli partizionati per i calcoli dei passaggi avanti e indietro, in parallelo al calcolo della GPU. Per i modelli di grandi dimensioni, eseguire l'operazione AllGather in modo efficiente è fondamentale per evitare problemi legati alla GPU e rallentare la velocità di addestramento. Quando viene attivato il parallelismo dei dati partizionati, i collettivi SMDDP entrano a far parte di questi collettivi AllGather critici in termini di prestazioni, migliorando la produttività dell'addestramento.

Addestramento con i collettivi SMDDP

Quando il processo di addestramento ha attivato il parallelismo dei dati partizionati e soddisfa i requisiti Supported configurations, i collettivi SMDDP vengono attivati automaticamente. Internamente, i collettivi SMDDP ottimizzano il collettivo AllGather per renderlo efficiente sull'infrastruttura AWS e si affidano a NCCL per tutti gli altri collettivi. Inoltre, in configurazioni non supportate, tutti i collettivi, incluso AllGather, utilizzano automaticamente il back-end NCCL.

A partire dalla versione 1.13.0 della libreria di parallelismo dei modelli SageMaker, il parametro "ddp_dist_backend" viene aggiunto alle opzioni modelparallel. Il valore predefinito per questo parametro di configurazione è "auto", che utilizza i collettivi SMDDP quando possibile, altrimenti ricorre a NCCL. Per forzare la libreria a utilizzare sempre NCCL, specifica "nccl" nel parametro di configurazione "ddp_dist_backend".

Il seguente esempio di codice mostra come configurare uno strumento di valutazione PyTorch utilizzando il parallelismo dei dati partizionati con il parametro "ddp_dist_backend", che è impostato su "auto" di default e, quindi, facoltativo da aggiungere.

import sagemaker from sagemaker.pytorch import PyTorch smp_options = { "enabled":True, "parameters": { "partitions": 1, "ddp": True, "sharded_data_parallel_degree": 64 "bf16": True, "ddp_dist_backend": "auto" # Specify "nccl" to force to use NCCL. } } mpi_options = { "enabled" : True, # Required "processes_per_host" : 8 # Required } smd_mp_estimator = PyTorch( entry_point="your_training_script.py", # Specify your train script source_dir="location_to_your_script", role=sagemaker.get_execution_role(), instance_count=8, instance_type='ml.p4d.24xlarge', framework_version='1.13.1', py_version='py3', distribution={ "smdistributed": {"modelparallel": smp_options}, "mpi": mpi_options }, base_job_name="sharded-data-parallel-demo", ) smd_mp_estimator.fit('s3://my_bucket/my_training_data/')

Configurazioni supportate

L'operazione AllGather con i collettivi SMDDP viene attivata nei processi di addestramento quando vengono soddisfatti tutti i seguenti requisiti di configurazione.

  • Il grado di parallelismo dei dati partizionati è maggiore di 1

  • Instance_count maggiore di 1

  • Instance_type uguale a ml.p4d.24xlarge

  • Container di addestramento SageMaker per PyTorch v1.12.1 o versione successiva

  • La libreria di parallelismo dei dati SageMaker v1.6.0 o versione successiva

  • La libreria di parallelismo dei modelli SageMaker v1.13.0 o versione successiva

Ottimizzazione delle prestazioni e della memoria

I collettivi SMDDP utilizzano memoria GPU aggiuntiva. Esistono due variabili di ambiente per configurare l'utilizzo della memoria della GPU a seconda dei diversi casi d'uso di addestramento del modello.

  • SMDDP_AG_SCRATCH_BUFFER_SIZE_BYTES: durante l'operazione AllGather SMDDP, il buffer di input AllGather viene copiato in un buffer temporaneo per la comunicazione tra i nodi. La variabile SMDDP_AG_SCRATCH_BUFFER_SIZE_BYTES controlla la dimensione (in byte) di questo buffer temporaneo. Se la dimensione del buffer temporaneo è inferiore alla dimensione del buffer di input AllGather, il collettivo AllGather torna a utilizzare NCCL.

    • Valore predefinito: 16 * 1024 * 1024 (16 MB)

    • Valori accettabili: qualsiasi multiplo di 8192

  • SMDDP_AG_SORT_BUFFER_SIZE_BYTES: la variabile SMDDP_AG_SORT_BUFFER_SIZE_BYTES serve a dimensionare il buffer temporaneo (in byte) per contenere i dati raccolti dalla comunicazione tra i nodi. Se la dimensione di questo buffer temporaneo è inferiore a 1/8 * sharded_data_parallel_degree * AllGather input size, il collettivo AllGather torna a utilizzare NCCL.

    • Valore predefinito: 128 * 1024 * 1024 (128 MB)

    • Valori accettabili: qualsiasi multiplo di 8192

Guida all'ottimizzazione delle variabili relative alla dimensione del buffer

I valori predefiniti per le variabili di ambiente dovrebbero funzionare bene per la maggior parte dei casi d'uso. Si consiglia di ottimizzare queste variabili solo se l'addestramento genera l'errore di esaurimento della memoria

L'elenco seguente illustra alcuni suggerimenti di ottimizzazione per ridurre l'ingombro di memoria della GPU dei collettivi SMDDP, preservando al contempo il miglioramento delle prestazioni che ne derivano.

  • Ottimizzazione SMDDP_AG_SCRATCH_BUFFER_SIZE_BYTES

    • La dimensione del buffer di input AllGather è inferiore per i modelli più piccoli. Pertanto, la dimensione richiesta per SMDDP_AG_SCRATCH_BUFFER_SIZE_BYTES può essere inferiore per i modelli con meno parametri.

    • La dimensione del buffer di input AllGather diminuisce all'aumentare di sharded_data_parallel_degree, poiché il modello viene partizionato suddiviso su più GPU. Pertanto, la dimensione richiesta per SMDDP_AG_SCRATCH_BUFFER_SIZE_BYTES può essere inferiore per processi di addestramento con valori grandi per sharded_data_parallel_degree.

  • Ottimizzazione SMDDP_AG_SORT_BUFFER_SIZE_BYTES

    • La quantità di dati raccolti dalla comunicazione tra nodi è inferiore per i modelli con un minor numero di parametri. Pertanto, la dimensione richiesta per SMDDP_AG_SORT_BUFFER_SIZE_BYTES può essere inferiore per tali modelli con un numero inferiore di parametri.

Alcuni collettivi potrebbero tornare a utilizzare NCCL; di conseguenza, potresti non ottenere il miglioramento delle prestazioni dai collettivi SMDDP ottimizzati. Se è disponibile memoria GPU aggiuntiva, è possibile valutare la possibilità di aumentare i valori SMDDP_AG_SCRATCH_BUFFER_SIZE_BYTES e SMDDP_AG_SORT_BUFFER_SIZE_BYTES per trarre vantaggio dall'aumento delle prestazioni.

Il codice seguente mostra come configurare le variabili di ambiente aggiungendole a mpi_options nel parametro di distribuzione dello strumento di valutazione PyTorch.

import sagemaker from sagemaker.pytorch import PyTorch smp_options = { .... # All modelparallel configuration options go here } mpi_options = { "enabled" : True, # Required "processes_per_host" : 8 # Required } # Use the following two lines to tune values of the environment variables for buffer mpioptions += " -x SMDDP_AG_SCRATCH_BUFFER_SIZE_BYTES=8192" mpioptions += " -x SMDDP_AG_SORT_BUFFER_SIZE_BYTES=8192" smd_mp_estimator = PyTorch( entry_point="your_training_script.py", # Specify your train script source_dir="location_to_your_script", role=sagemaker.get_execution_role(), instance_count=8, instance_type='ml.p4d.24xlarge', framework_version='1.13.1', py_version='py3', distribution={ "smdistributed": {"modelparallel": smp_options}, "mpi": mpi_options }, base_job_name="sharded-data-parallel-demo-with-tuning", ) smd_mp_estimator.fit('s3://my_bucket/my_training_data/')

Addestramento misto di precisione con parallelismo di dati partizionati

Per risparmiare ulteriormente la memoria della GPU con numeri in virgola mobile a semiprecisione e parallelismo dei dati partizionati, puoi attivare il formato a virgola mobile a 16 bit (FP16) o il formato Brain floating point (BF16) aggiungendo un parametro aggiuntivo alla configurazione di addestramento distribuito.

Nota

L'addestramento misto di precisione con parallelismo dei dati partizionati è disponibile nella libreria di parallelismo dei modelli SageMaker v1.11.0 e versioni successive.

Per l'addestramento FP16 con Parallelismo dei dati partizionati

Per eseguire l'addestramento sull'FP16 con parallelismo dei dati partizionati, aggiungi "fp16": True" al dizionario di configurazione smp_options. Nello script di addestramento, puoi scegliere tra le opzioni di dimensionamento delle perdite statiche e dinamiche tramite il modulo smp.DistributedOptimizer. Per ulteriori informazioni, consulta Addestramento FP16 con parallelismo dei modelli.

smp_options = { "enabled": True, "parameters": { "ddp": True, "sharded_data_parallel_degree": 2, "fp16": True } }

Per l'addestramento BF16 con Parallelismo dei dati partizionati

La funzionalità di parallelizzazione dei dati sottoposti a sharding di SageMaker AI supporta l’addestramento nel tipo di dati BF16. Il tipo di dati BF16 utilizza 8 bit per rappresentare l'esponente di un numero in virgola mobile, mentre il tipo di dati FP16 utilizza 5 bit. La conservazione degli 8 bit per l'esponente consente di mantenere la stessa rappresentazione dell'esponente di un numero a virgola mobile (FP32) a 32 bit. Ciò rende la conversione tra FP32 e BF16 più semplice e significativamente meno soggetta a problemi di overflow e underflow che si presentano spesso durante l'addestramento dell'FP16, specialmente quando si addestrano modelli più grandi. Sebbene entrambi i tipi di dati utilizzino 16 bit in totale, questo maggiore intervallo di rappresentazione dell'esponente nel formato BF16 va a scapito della riduzione della precisione. Per l'addestramento di modelli di grandi dimensioni, questa precisione ridotta è spesso considerata un compromesso accettabile per quanto riguarda la portata e la stabilità dell'addestramento.

Nota

Attualmente, l'addestramento BF16 funziona solo quando è attivato il parallelismo dei dati partizionati.

Per eseguire l'addestramento sul BF16 con parallelismo dei dati partizionati, aggiungi "bf16": True al dizionario di configurazione smp_options.

smp_options = { "enabled": True, "parameters": { "ddp": True, "sharded_data_parallel_degree": 2, "bf16": True } }

Parallelismo dei dati partizionati con parallelismo tensoriale

Se utilizzi il parallelismo dei dati partizionati e devi anche ridurre la dimensione globale del batch, prendi in considerazione l'utilizzo del parallelismo tensoriale con il parallelismo dei dati partizionati. Quando si addestra un modello di grandi dimensioni con parallelismo dei dati partizionati su un cluster di elaborazione molto grande (in genere 128 nodi o più), anche un batch di piccole dimensioni per GPU si traduce in un batch globale di dimensioni molto grandi. Potrebbe portare a problemi di convergenza o a basse prestazioni di calcolo. La riduzione della dimensione del batch per GPU a volte non è possibile con il solo parallelismo dei dati partizionati, quando un singolo batch è già di grandi dimensioni e non può essere ulteriormente ridotto. In questi casi, l'utilizzo del parallelismo dei dati partizionati in combinazione con il parallelismo tensoriale aiuta a ridurre la dimensione globale del batch.

La scelta dei gradi ottimali partizionati di parallelismo dei dati e dei tensori dipende dalla scala del modello, dal tipo di istanza e dalla dimensione globale del batch che è ragionevole per la convergenza del modello. Ti consigliamo di iniziare da un grado di parallelo tensoriale basso per adattare la dimensione globale del batch al cluster di calcolo per risolvere gli errori di esaurimento della memoria CUDA e ottenere le migliori prestazioni. Guarda i due casi di esempio seguenti per scoprire come la combinazione di parallelismo tensoriale e parallelismo dei dati partizionati aiuta a regolare la dimensione globale del batch raggruppando le GPU per il parallelismo del modello, con conseguente minor numero di repliche del modello e una dimensione globale del batch inferiore.

Nota

Questa funzionalità è disponibile nella libreria di parallelismo dei modelli SageMaker v1.15 e supporta PyTorch v1.13.1.

Nota

Questa funzionalità è disponibile per i modelli supportati dalla funzionalità di parallelismo tensoriale della libreria. Per trovare l'elenco dei modelli supportati, consulta Supporto per i modelli Hugging Face Transformer. Tieni inoltre presente che devi passare tensor_parallelism=True all'argomento smp.model_creation mentre modifichi lo script di addestramento. Per ulteriori informazioni, consulta lo script di addestramentotrain_gpt_simple.py nel repository GitHub degli esempi di SageMaker AI.

Esempio 1

Supponiamo di voler addestrare un modello su un cluster di 1536 GPU (192 nodi con 8 GPU ciascuno), impostando il grado di parallelismo dei dati partizionati su 32 (sharded_data_parallel_degree=32) e la dimensione del batch per GPU su 1, dove ogni batch ha una lunghezza di sequenza di 4096 token. In questo caso, ci sono 1536 repliche di modelli, la dimensione globale del batch diventa 1536 e ogni batch globale contiene circa 6 milioni di token.

(1536 GPUs) * (1 batch per GPU) = (1536 global batches) (1536 batches) * (4096 tokens per batch) = (6,291,456 tokens)

L'aggiunta del parallelismo tensoriale può ridurre la dimensione globale del batch. Un esempio di configurazione può essere l'impostazione del grado parallelo tensoriale su 8 e la dimensione del batch per GPU su 4. Questo forma 192 gruppi tensoriali paralleli o 192 repliche di modelli, in cui ogni replica del modello è partizionata su 8 GPU. La dimensione del batch di 4 è la quantità di dati di addestramento per iterazione e per gruppo parallelo di tensori; ovvero, ogni replica del modello consuma 4 batch per iterazione. In questo caso, la dimensione globale del batch diventa 768 e ogni batch globale contiene circa 3 milioni di token. Pertanto, la dimensione globale del batch è ridotta della metà rispetto al caso precedente con il solo parallelismo dei dati partizionati.

(1536 GPUs) / (8 tensor parallel degree) = (192 tensor parallelism groups) (192 tensor parallelism groups) * (4 batches per tensor parallelism group) = (768 global batches) (768 batches) * (4096 tokens per batch) = (3,145,728 tokens)

Esempio 2

Quando sono attivati sia il parallelismo dei dati partizionati che il parallelismo tensoriale, la libreria applica innanzitutto il parallelismo tensoriale e partiziona il modello in questa dimensione. Per ogni classificazione parallela dei tensori, il parallelismo dei dati viene applicato come per sharded_data_parallel_degree.

Ad esempio, supponiamo di voler impostare 32 GPU con un grado di parallelismo tensoriale di 4 (formando gruppi di 4 GPU), un grado di parallelismo dei dati partizionati di 4, per finire con un grado di replica di 2. L'assegnazione crea otto gruppi di GPU in base al grado di parallelismo tensoriale come segue: (0,1,2,3), (4,5,6,7), (8,9,10,11), (12,13,14,15), (16,17,18,19), (20,21,22,23), (24,25,26,27), (28,29,30,31). Cioè, quattro GPU formano un gruppo parallelo tensoriale. In questo caso, il gruppo parallelo di dati ridotto per le GPU di livello 0 dei gruppi paralleli tensoriali sarebbe (0,4,8,12,16,20,24,28). Il gruppo parallelo di dati ridotto viene partizionato in base al grado di parallelismo dei dati partizionati pari a 4, ottenendo due gruppi di replica per il parallelismo dei dati. Le GPU (0,4,8,12) formano un gruppo di partizioni, che collettivamente contengono una copia completa di tutti i parametri per la classificazione 0 dei tensori parallela, e le GPU (16,20,24,28) formano un altro gruppo di questo tipo. Anche altre classificazioni tensoriali parallele hanno gruppi di partizioni e replica simili.

Figura 1: Gruppi di parallelizzazione tensoriale.

Figura 1: Gruppi di parallelizzazione tensoriale per (nodi, grado di parallelizzazione dei dati sottoposti a sharding, grado di parallelizzazione tensoriale) = (4, 4, 4), dove ogni rettangolo rappresenta una GPU con indici da 0 a 31. Le GPU formano gruppi di parallelizzazione tensoriale da TPG0 a TPG7. I gruppi di replica sono ({TPG0, TPG4}, {TPG1, TPG5}, {TPG2, TPG6} e {TPG3, TPG7}); ogni coppia di gruppi di replica condivide lo stesso colore, ma presenta un riempimento diverso.

Figura 2: Gruppi di parallelizzazione dei dati sottoposti a sharding.

Figura 2: Gruppi di parallelizzazione dei dati sottoposti a sharding (nodi, grado di parallelizzazione dei dati sottoposti a sharding, grado di parallelizzazione tensoriale) = (4, 4, 4), dove ogni rettangolo rappresenta una GPU con indici da 0 a 31. Le GPU formano gruppi di parallelizzazione dei dati sottoposti a sharding da SDPG0 a SDPG7. I gruppi di replica sono ({SDPG0, SDPG4}, {SDPG1, SDPG5}, {SDPG2, SDPG6} e {SDPG3, SDPG7}); ogni coppia di gruppi di replica condivide lo stesso colore, ma presenta un riempimento diverso.

Come attivare il parallelismo dei dati partizionati con il parallelismo tensoriale

Per utilizzare il parallelismo dei dati partizionati con il parallelismo tensoriale, è necessario impostarli sia sharded_data_parallel_degree che tensor_parallel_degree nella configurazione per distribution mentre si crea un oggetto della classe dello strumento di valutazione SageMaker PyTorch.

È inoltre necessario attivare prescaled_batch. Ciò significa che, invece di leggere il proprio batch di dati, ogni gruppo parallelo tensoriale legge collettivamente un batch combinato della dimensione del batch scelta. In effetti, invece di dividere il set di dati in parti uguali al numero di GPU (o dimensione parallela dei dati smp.dp_size()), lo divide in parti uguali al numero di GPU diviso per tensor_parallel_degree (chiamato anche dimensione parallela dei dati ridotta smp.rdp_size()). Per maggiori dettagli sul batch pre-dimensionato, vedere Batch pre-dimensionato nella documentazione di SDK Python di SageMaker. Consulta anche lo script di addestramento di esempio train_gpt_simple.py per GPT-2 nel repository GitHub degli esempi di SageMaker AI.

Il seguente frammento di codice mostra un esempio di creazione di un oggetto dello strumento di valutazione PyTorch basato sullo scenario di cui sopra in Esempio 2.

mpi_options = "-verbose --mca orte_base_help_aggregate 0 " smp_parameters = { "ddp": True, "fp16": True, "prescaled_batch": True, "sharded_data_parallel_degree": 4, "tensor_parallel_degree": 4 } pytorch_estimator = PyTorch( entry_point="your_training_script.py", role=role, instance_type="ml.p4d.24xlarge", volume_size=200, instance_count=4, sagemaker_session=sagemaker_session, py_version="py3", framework_version="1.13.1", distribution={ "smdistributed": { "modelparallel": { "enabled": True, "parameters": smp_parameters, } }, "mpi": { "enabled": True, "processes_per_host": 8, "custom_mpi_options": mpi_options, }, }, source_dir="source_directory_of_your_code", output_path=s3_output_location )

Suggerimenti e considerazioni per l'utilizzo del parallelismo dei dati partizionati

Quando utilizzi il parallelismo dei dati partizionati della libreria di parallelismo dei modelli SageMaker considera quanto segue.

  • Il parallelismo dei dati partizionati è compatibile con l'addestramento FP16. Per eseguire l'addestramento FP16, consulta la sezione Addestramento FP16 con parallelismo dei modelli.

  • Il parallelismo dei dati partizionati è compatibile con il parallelismo tensoriale. I seguenti elementi sono ciò che potresti dover considerare per utilizzare il parallelismo dei dati partizionati con il parallelismo tensoriale.

    • Quando si utilizza il parallelismo dei dati partizionati con il parallelismo tensoriale, anche i livelli di incorporamento vengono distribuiti automaticamente nel gruppo parallelo tensoriale. In altre parole, il parametro distribute_embedding viene impostato automaticamente su True. Per maggiori informazioni sul parallelismo tensoriale, consulta Parallelismo tensoriale.

    • Si noti che il parallelismo dei dati partizionati con il parallelismo tensoriale attualmente utilizza i collettivi NCCL come back-end della strategia di addestramento distribuito.

    Per ulteriori informazioni, consulta la sezione Parallelismo dei dati partizionati con parallelismo tensoriale.

  • Il parallelismo dei dati partizionati attualmente non è compatibile con il parallelismo di pipeline o il partizionamento dello stato dell'ottimizzatore. Per attivare il parallelismo dei dati partizionati, disattiva il partizionamento dello stato dell'ottimizzatore e imposta il grado di parallelismo della pipeline su 1.

  • Le funzionalità checkpoint di attivazione e offload di attivazione sono compatibili con il parallelismo dei dati partizionati.

  • Per utilizzare il parallelismo dei dati partizionati con l'accumulo di gradienti, impostate l'argomento backward_passes_per_step sul numero di fasi di accumulo mentre effettui il wrapping del modello con il modulo smdistributed.modelparallel.torch.DistributedModel. Ciò garantisce che l'operazione AllReduce del gradiente tra i gruppi di replica del modello (gruppi di partizionamento) avvenga al limite dell'accumulo del gradiente.

  • Puoi eseguire il checkpoint dei tuoi modelli addestrati con il parallelismo dei dati partizionati utilizzando le API di checkpoint della libreria smp.save_checkpoint e smp.resume_from_checkpoint. Per ulteriori informazioni, consulta Checkpointing di un modello PyTorch distribuito (per la libreria di parallelismo del modello SageMaker v1.10.0 e successive).

  • Il comportamento del parametro di configurazione delayed_parameter_initialization cambia in base al parallelismo dei dati partizionati. Quando queste due funzionalità sono attivate contemporaneamente, i parametri vengono inizializzati immediatamente dopo la creazione del modello in modo partizionato anziché ritardare l'inizializzazione dei parametri, in modo che ogni classificazione inizializzi e memorizzi la propria partizione di parametri.

  • Quando è attivato il parallelismo dei dati partizionati, la libreria esegue internamente il ritaglio del gradiente durante l'esecuzione della chiamata optimizer.step(). Non è necessario utilizzare API di utilità per il ritaglio del gradiente, ad esempio torch.nn.utils.clip_grad_norm_(). Per regolare il valore di soglia del ritaglio del gradiente, è possibile impostarlo tramite il parametro sdp_gradient_clipping per la configurazione dei parametri di distribuzione quando si costruisce lo strumento di valutazione SageMaker PyTorch, come mostrato nella sezione Come applicare il parallelismo dei dati partizionati al tuo processo di addestramento.