Pipeline Parallelism
Il parallelismo della pipeline colloca strati consecutivi di un modello su GPU diverse e vi fa passare mini-batch, consentendo di addestrare un modello più grande di quanto possa contenere una sola GPU.
Il parallelismo a pipeline è una tecnica di addestramento distribuito che suddivide una rete neurale lungo la sua profondità in gruppi consecutivi di strati chiamati stadi, colloca ogni stadio sulla propria GPU e trasferisce le attivazioni da uno stadio al successivo. Per mantenere occupate tutte le GPU, ogni batch viene suddiviso in micro-batch più piccoli che attraversano gli stadi come pezzi su una catena di montaggio. È chiamato anche parallelismo del modello tra gli strati. Nel novembre 2018, i ricercatori di Google guidati da Yanping Huang hanno reso popolare l'approccio dei micro-batch con GPipe, addestrando un modello AmoebaNet da 557 milioni di parametri fino a raggiungere un'accuratezza top-1 dell'84,4% su ImageNet e un Transformer per la traduzione multilingue con 6 miliardi di parametri e 128 strati.
Micro-batch e bolla della pipeline#
Con un batch alla volta, lavora un solo stadio mentre gli altri attendono: lo stadio 2 non può iniziare finché lo stadio 1 non ha terminato, e durante la retropropagazione l'ordine si inverte. I micro-batch permettono allo stadio 1 di avviare il secondo micro-batch non appena passa il primo allo stadio 2. Gli intervalli inattivi che rimangono mentre la pipeline si riempie e si svuota sono chiamati bolla. Stampando una pianificazione forward in stile GPipe per 4 stadi e 6 micro-batch se ne vede la struttura:
stages, micro_batches = 4, 6
steps = micro_batches + stages - 1 # time steps until the last micro-batch leaves the last stage
for stage in range(stages):
row = ""
for t in range(steps):
m = t - stage # stage s starts micro-batch m once stage s-1 hands it over
row += f" F{m}" if 0 <= m < micro_batches else " ."
print(f"GPU {stage}:{row}")
# Every stage idles for stages - 1 of the steps, in the forward and again in the backward pass
bubble = (stages - 1) / steps
print(f"Idle fraction: {bubble:.0%}")L'output è una scala: la GPU 0 esegue i passaggi forward da F0 a F5 nei primi sei dei nove passaggi, poi attende; la GPU 3 attende tre passaggi prima di avviare F0, e l'ultima riga è Idle fraction: 33%. La frazione di bolla è (stadi − 1) / (micro-batch + stadi − 1), quindi 24 micro-batch attraverso gli stessi 4 stadi la riducono all'11%. I gradienti di tutti i micro-batch vengono sommati prima di un singolo passaggio dell'ottimizzatore, con lo stesso calcolo dell'accumulo dei gradienti, quindi l'aggiornamento corrisponde all'addestramento sull'intero batch. GPipe scarta anche le attivazioni all'interno di ogni stadio e le ricalcola durante il passaggio backward, una forma di checkpointing dei gradienti.
Pianificazioni della pipeline#
Le pianificazioni successive riordinano lo stesso lavoro per risparmiare memoria o ridurre la bolla:
- 1F1B: Introdotta dal sistema PipeDream nel 2018, alterna un micro-batch forward e uno backward per stadio una volta che la pipeline è piena. Ogni stadio conserva quindi le attivazioni al massimo per un numero di micro-batch pari agli stadi, anziché conservarle tutte.
- 1F1B intercalata: assegna a ogni GPU diversi stadi più piccoli e non adiacenti. Il team Megatron-LM di NVIDIA ha riportato un throughput superiore di oltre il 10% e ha addestrato un modello da 1 trilione di parametri a 502 petaFLOP/s su 3.072 GPU, pari al 52% delle prestazioni di picco.
- Zero bubble: suddivide il passaggio backward nel gradiente dell'input dello stadio, atteso dallo stadio precedente, e nel gradiente dei pesi, che può occupare in seguito gli intervalli inattivi. Supera il throughput di 1F1B fino al 23% a parità di budget di memoria.
PyTorch li fornisce come ScheduleGPipe, Schedule1F1B, ScheduleInterleaved1F1B, ScheduleInterleavedZeroBubble e ScheduleDualPipeV nella sua API di pipelining, che suddivide anche un modello in stadi. DualPipe proviene da DeepSeek-V3, il cui team ha eseguito 16 stadi di pipeline e l'ha utilizzato per sovrapporre il calcolo alla comunicazione e ridurre la bolla.
Il ruolo del parallelismo a pipeline#
Gli stadi si scambiano solo le attivazioni ai rispettivi confini, una volta per micro-batch, quindi il parallelismo a pipeline tollera collegamenti più lenti tra server meglio del parallelismo tensoriale, che comunica all'interno di ogni layer. Perciò, le grandi esecuzioni di addestramento combinano i due approcci. Meta ha addestrato Llama 3 405B con parallelismo tensoriale a 8 vie all'interno di ogni server a 8 GPU, 16 stadi di pipeline tra server e parallelismo dei dati su 64-128 repliche; anche motori di serving come vLLM utilizzano la stessa suddivisione quando un modello linguistico di grandi dimensioni (LLM) richiede più di un nodo. Lo stadio più lento determina il ritmo dell'intera pipeline, e il primo e l'ultimo stadio di un modello linguistico includono anche la tabella degli embedding e il layer di output, quindi Llama 3 ha assegnato a ciascuno di essi un layer Transformer in meno.
Gli approcci correlati suddividono il lavoro in modo diverso:
- Parallelismo tensoriale: suddivide le matrici dei pesi all'interno di ogni layer, così ogni GPU partecipa a tutti i layer.
- Parallelismo del contesto: suddivide una sequenza di input lunga tra più GPU.
- Apprendimento suddiviso: suddivide anch'esso una rete in profondità, ma tra organizzazioni, così che il proprietario dei dati non invii mai dati grezzi al server che esegue i layer successivi.
Il parallelismo dei dati mantiene ogni layer su ogni GPU e suddivide invece il batch: è tutto ciò di cui un modello ha bisogno quando entra in un solo dispositivo. È così che Ultralytics YOLO26 si addestra su più GPU: con device=[0, 1, 2, 3] e batch=64 in modalità di addestramento, ogni GPU esegue il modello completo di rilevamento degli oggetti su 16 immagini e PyTorch DistributedDataParallel calcola la media dei gradienti tra le GPU dopo ogni passaggio backward.










