Expert Parallelism
Il parallelismo degli esperti distribuisce gli esperti dei livelli mixture-of-experts su più GPU e instrada ogni token verso di loro tramite comunicazione all-to-all.
Il parallelismo degli esperti (EP) è una strategia di addestramento distribuito e inferenza per i modelli a miscela di esperti (MoE), che assegna esperti diversi a GPU diverse e invia ogni token ai dispositivi che ospitano gli esperti selezionati per quel token. Un livello MoE sostituisce un grande blocco feed-forward di un transformer con molte reti di esperti più piccole e un router che attiva solo pochi esperti per token; così, il numero totale di parametri può aumentare molto più rapidamente del calcolo necessario per ogni token. Il parallelismo degli esperti consente di mantenere quei parametri in memoria: invece di memorizzare tutti gli esperti su ogni GPU, ciascuna GPU ne conserva una parte. Già nel 2017 Noam Shazeer e i colleghi di Google distribuivano gli esperti tra i dispositivi, con una copia condivisa per ciascuno, nel loro livello MoE a gating sparso; GShard ampliò l’approccio nel giugno 2020, distribuendo gli esperti di un modello di traduzione con oltre 600 miliardi di parametri su 2.048 acceleratori TPU v3. Il parallelismo degli esperti è ormai standard per l’addestramento e la distribuzione di grandi modelli MoE per il linguaggio e la visione-linguaggio.
Come si spostano i token tra le GPU#
Ogni livello MoE si articola in quattro passaggi:
- Instradamento: il router assegna un punteggio a ogni token rispetto a ogni esperto e seleziona i primi k esperti, in genere uno, due o otto.
- Instradamento: Una comunicazione collettiva all-to-all invia lo stato nascosto di ciascun token alle GPU che ospitano gli esperti selezionati.
- Calcolo: ogni GPU esegue i propri esperti locali sui token ricevuti.
- Combinazione: una seconda comunicazione all-to-all restituisce gli output alla GPU originale di ogni token, dove vengono ponderati in base ai punteggi del router e sommati.
Il frammento seguente simula i passaggi di instradamento e invio di un livello con 8 esperti distribuiti su 4 GPU, due esperti per GPU:
import torch
torch.manual_seed(0)
num_experts, num_gpus, top_k = 8, 4, 2
tokens = torch.randn(4096, 512) # stati nascosti per 4.096 token
router = torch.nn.Linear(512, num_experts)
# Instradamento: ogni token seleziona i 2 esperti con i punteggi più alti del router
with torch.no_grad():
_, experts = router(tokens).topk(top_k, dim=-1)
# Parallelismo degli esperti: gli esperti 0-1 sono sulla GPU 0, gli esperti 2-3 sulla GPU 1 e così via
gpu = experts // (num_experts // num_gpus)
# Invio: conta le assegnazioni token-esperto ricevute da ogni esperto e GPU
print(torch.bincount(experts.flatten(), minlength=num_experts).tolist())
print(torch.bincount(gpu.flatten(), minlength=num_gpus).tolist())La prima riga dell'output mostra il carico di ogni esperto, da 948 a 1.087 assegnazioni rispetto a una quota equa di 1.024; la seconda mostra che le quattro GPU ricevono da 1.968 a 2.139 delle 8.192 assegnazioni. Anche un router inizializzato casualmente distribuisce il lavoro in modo disomogeneo; i router addestrati sviluppano inoltre esperti popolari che sbilanciano il carico molto di più.
Bilanciamento del carico e capacità#
Un livello termina solo quando termina la GPU più occupata, quindi lo sbilanciamento dell'instradamento si traduce direttamente in hardware inattivo. L'addestramento MoE lo contrasta in tre modi:
- Perdita ausiliaria di bilanciamento: Un termine aggiuntivo nella funzione di perdita premia il router quando distribuisce uniformemente i token tra gli esperti.
- Fattore di capacità: Ogni esperto accetta al massimo un numero fisso di token per batch, per esempio 1.25 volte la quota equa; i token eccedenti saltano quell’esperto.
- Bilanciamento basato sui bias: DeepSeek-V3 aggiunge ai punteggi del router un bias per esperto che incide soltanto sulla scelta degli esperti; dopo ogni passaggio, lo riduce per gli esperti sovraccarichi e lo aumenta per quelli inattivi, bilanciando il carico senza una perdita ausiliaria in competizione con l’obiettivo principale.
Con un limite di capacità, il percorso di ciascun token dipende dal carico dei suoi esperti:
Un token saltato prosegue invariato attraverso la connessione residua, quindi un’eliminazione consistente riduce la qualità. DeepSeek-V3 non elimina token durante l’addestramento e si affida invece al bilanciamento basato sui bias.
La comunicazione è l’altro costo. I due scambi all-to-all avvengono in ogni livello MoE, perciò il parallelismo degli esperti funziona meglio all’interno di un nodo, dove le GPU condividono connessioni NVLink veloci, e diventa costoso attraverso i collegamenti più lenti tra nodi. DeepSeek-V3 distribuisce i 256 esperti instradati per livello con parallelismo degli esperti a 64 vie su 8 nodi, invia ogni token agli esperti di non più di 4 nodi e sovrappone gli scambi ai calcoli.
Combinare le strategie di parallelismo#
Il parallelismo degli esperti è uno dei diversi modi per suddividere l’addestramento tra dispositivi:
- Parallelismo dei dati: Replica il modello completo su ogni GPU e divide ciascun batch, sincronizzando i gradienti dopo ogni passaggio.
- Parallelismo dei tensori: Suddivide le singole matrici dei pesi tra le GPU, così ogni GPU partecipa a ogni livello.
- Parallelismo della pipeline: Assegna livelli consecutivi a GPU diverse e vi invia micro-batch in sequenza.
- Parallelismo del contesto: Suddivide una singola sequenza di input lunga tra le GPU.
I modelli densi che entrano in una GPU non hanno bisogno di altro che del parallelismo dei dati: è così che Ultralytics YOLO26 si addestra su più GPU quando viene passato un elenco di dispositivi come device=[0, 1] in modalità di addestramento. I grandi modelli MoE combinano diverse forme di parallelismo: DeepSeek-V3 ha addestrato i suoi 671 miliardi di parametri, di cui 37 miliardi attivi per token, con un parallelismo della pipeline a 16 vie, un parallelismo degli esperti a 64 vie e un parallelismo dei dati con suddivisione in shard, senza parallelismo dei tensori. I motori di inferenza come vLLM applicano la stessa suddivisione quando servono un modello: così un modello MoE i cui esperti supererebbero la memoria di una singola GPU viene eseguito su più GPU, ciascuna delle quali contiene solo la propria parte degli esperti.










