La traduzione dell'articolo è stata preparata in vista dell'inizio del corso
L'apprendimento distribuito su più istanze computazionali ad alte prestazioni può ridurre il tempo di addestramento delle moderne reti neurali profonde su grandi volumi di dati da settimane a ore o addirittura a minuti, rendendo questa tecnica prevalente per l'uso pratico dell'apprendimento profondo. Gli utenti devono comprendere come condividere e sincronizzare i dati tra le diverse istanze, il che influisce notevolmente sull'efficienza della scalabilità. Inoltre, gli utenti devono sapere come distribuire uno script di addestramento su più istanze, che funziona su un'unica istanza.
In questo articolo parleremo di un modo rapido e semplice di apprendimento distribuito utilizzando la libreria open source per l'apprendimento profondo Apache MXNet e il framework di apprendimento distribuito Horovod. Mostreremo chiaramente i vantaggi del framework Horovod in termini di prestazioni e dimostreremo come scrivere uno script di addestramento MXNet affinché funzioni in modo distribuito con Horovod.
Cos'è Apache MXNet
– un framework open source per il deep learning, utilizzato per costruire, addestrare e implementare reti neurali profonde. MXNet astrae le complessità associate all'implementazione delle reti neurali, offre elevate prestazioni e scalabilità, oltre a fornire API per linguaggi di programmazione popolari come , , , , , , e altro ancora.
Apprendimento distribuito in MXNet con il server dei parametri
utilizza un approccio basato su server dei parametri. Impiega un insieme di server dei parametri per raccogliere i gradienti da ciascun worker, eseguire l'aggregazione e inviare i gradienti aggiornati di nuovo ai worker per la successiva iterazione di ottimizzazione. Determinare il giusto rapporto tra server e worker è fondamentale per uno scaling efficace. Se c'è solo un server dei parametri, questo può diventare un collo di bottiglia nelle computazioni. Viceversa, se se ne utilizzano troppi, la comunicazione “molti-a-molti” può saturare tutte le connessioni di rete.
Che cos'è Horovod
– un framework aperto per l'apprendimento profondo distribuito, sviluppato da Uber. Utilizza tecnologie efficienti per l'interazione tra più GPU e nodi, come NVIDIA Collective Communications Library (NCCL) e Message Passing Interface (MPI) per distribuire e aggregare i parametri del modello tra i worker. Ottimizza l'uso della larghezza di banda della rete e si scala bene quando si lavora con modelli di reti neurali profonde. Attualmente supporta diversi framework di machine learning popolari, in particolare , Tensorflow, Keras e PyTorch.
Integrazione di MXNet e Horovod
MXNet si integra con Horovod attraverso l'API di apprendimento distribuito definite in Horovod. In Horovod, le API di comunicazione horovod.broadcast(), horovod.allgather() e horovod.allreduce() sono implementate utilizzando callback asincrone del motore MXNet, come parte del suo grafo delle operazioni. Pertanto, le dipendenze dei dati tra comunicazione e calcoli vengono gestite facilmente dal motore MXNet, per evitare perdite di prestazioni dovute alla sincronizzazione. L'oggetto ottimizzatore distribuito, definito in Horovod horovod.DistributedOptimizer si espande Optimizer In MXNet, implement it in such a way that it invokes the corresponding Horovod APIs for distributed parameter updates. All these implementation details are transparent to end users.
Avvio rapido
Puoi iniziare rapidamente ad addestrare una piccola rete neurale convoluzionale sul dataset MNIST utilizzando MXNet e Horovod sul tuo MacBook.
Per cominciare, installa mxnet e horovod da PyPI:
pip install mxnet
pip install horovodNota: Se riscontri un errore durante pip install horovod, potrebbe essere necessario aggiungere la variabile MACOSX_DEPLOYMENT_TARGET=10.vv, dove vv – è la versione del tuo MacOS, ad esempio, per MacOSX Sierra dovrai scrivere MACOSX_DEPLOYMENT_TARGET=10.12 pip install horovod
Successivamente, installa OpenMPI .
Infine scarica lo script di test mxnet_mnist.py ed esegui i seguenti comandi nel terminale del MacBook nella directory di lavoro:
mpirun -np 2 -H localhost:2 -bind-to none -map-by slot python mxnet_mnist.pyIn questo modo avvierai l'addestramento su due core del tuo processore. L'uscita sarà la seguente:
INFO:root:Epoch[0] Batch [0-50] Speed: 2248.71 samples/sec accuracy=0.583640
INFO:root:Epoch[0] Batch [50-100] Speed: 2273.89 samples/sec accuracy=0.882812
INFO:root:Epoch[0] Batch [50-100] Speed: 2273.39 samples/sec accuracy=0.870000Dimostrazione delle prestazioni
Durante l'addestramento del modello ResNet50-v1 sul dataset ImageNet utilizzando 64 GPU con otto istanze p3.16xlarge EC2, ciascuna contenente 8 GPU NVIDIA Tesla V100 nel cloud AWS, abbiamo raggiunto una capacità di addestramento di 45.000 immagini/secondo (cioè il numero di campioni addestrati al secondo). L'addestramento si è concluso dopo 44 minuti e 90 epoche con la migliore precisione del 75,7%. p3.16xlarge Abbiamo confrontato questo con l'addestramento distribuito di MXNet utilizzando un approccio di server dei parametri su 8, 16, 32 e 64 GPU con un server con un singolo parametro e un rapporto server-worker di 1 a 1 e 2 a 1 rispettivamente. Il risultato è visibile nella Figura 1 qui sotto. Sull'asse y a sinistra, le colonne riflettono il numero di immagini per l'addestramento al secondo, mentre le linee mostrano l'efficienza di scalabilità (ovvero il rapporto tra la capacità effettiva e quella ideale) sull'asse y a destra. Come potete vedere, la scelta del numero di server influenza l'efficienza di scalabilità. Se il server dei parametri è unico, l'efficienza di scalabilità scende al 38% su 64 GPU. Per ottenere la stessa efficienza di scalabilità ottenuta con Horovod, è necessario raddoppiare il numero di server rispetto al numero di worker.
p3.16xlarge

Figura 1. Confronto tra l'apprendimento distribuito utilizzando MXNet con Horovod e con il server dei parametri
Nella Tabella 1 sottostante abbiamo confrontato il costo finale dell'istanza durante l'esecuzione di esperimenti su 64 GPU. Utilizzare MXNet insieme a Horovod offre la migliore larghezza di banda al minor costo.

Tabella 1. Confronto dei costi tra Horovod e il server dei parametri con un rapporto server-lavoratori di 2 a 1.
Passi per la riproduzione
Nei seguenti passaggi ti mostreremo come riprodurre il risultato dell'apprendimento distribuito utilizzando MXNet e Horovod. Per saperne di più sull'apprendimento distribuito con MXNet, leggi .
Passo 1
Crea un cluster di istanze omogenee con MXNet versione 1.4.0 o superiore e Horovod versione 0.16.0 o superiore per utilizzare l'apprendimento distribuito. Dovrai anche installare le librerie per l'apprendimento su GPU. Per le nostre istanze abbiamo scelto Ubuntu 16.04 Linux, con Driver GPU 396.44, CUDA 9.2, libreria cuDNN 7.2.1, comunicatore NCCL 2.2.13 e OpenMPI 3.1.1. Puoi anche utilizzare , dove queste librerie sono già preinstallate.
Passo 2
Aggiungi al tuo script di addestramento MXNet la possibilità di lavorare con l'API Horovod. Lo script sottostante basato su MXNet Gluon API può essere utilizzato come un semplice modello. Le righe evidenziate in grassetto sono necessarie se hai già uno script di addestramento corrispondente. Ecco alcune modifiche critiche che devono essere apportate per l'addestramento con Horovod:
- Imposta il contesto in base al rango locale di Horovod (riga 8), in modo da comprendere che l'addestramento viene eseguito sulla corretta GPU.
- Passa i parametri iniziali da un lavoratore a tutti (riga 18), per assicurarti che tutti i lavoratori inizino con gli stessi parametri iniziali.
- Crea Horovod DistributedOptimizer (riga 25), per aggiornare i parametri in modo distribuito.
Per ottenere lo script completo, consulta gli esempi Horovod-MXNet e .
1 import mxnet as mx
2 import horovod.mxnet as hvd
3
4 # Horovod: inizializza Horovod
5 hvd.init()
6
7 # Horovod: assegna una GPU da usare al rango locale
8 context = mx.gpu(hvd.local_rank())
9
10 # Costruisci il modello
11 model = ...
12
13 # Inizializza i parametri
14 model.initialize(initializer, ctx=context)
15 params = model.collect_params()
16
17 # Horovod: trasmetti i parametri
18 hvd.broadcast_parameters(params, root_rank=0)
19
20 # Crea l'ottimizzatore
21 optimizer_params = ...
22 opt = mx.optimizer.create('sgd', **optimizer_params)
23
24 # Horovod: avvolgi l'ottimizzatore con DistributedOptimizer
25 opt = hvd.DistributedOptimizer(opt)
26
27 # Crea il trainer e la funzione di perdita
28 trainer = mx.gluon.Trainer(params, opt, kvstore=None)
29 loss_fn = ...
30
31 # Allena il modello
32 for epoch in range(num_epoch):
33 ...Passo 3
Accedi a uno dei worker per avviare l'apprendimento distribuito utilizzando le direttive MPI. In questo esempio, l'apprendimento distribuito viene avviato su quattro istanze con 4 GPU ciascuna, per un totale di 16 GPU nel cluster. Verrà utilizzato l'ottimizzatore di discesa del gradiente stocastico (SGD) con i seguenti iperparametri:
- dimensione del mini-batch: 256
- tasso di apprendimento: 0.1
- momento: 0.9
- decadimento del peso: 0.0001
Man mano che scalavamo da una GPU a 64 GPU, abbiamo scalato linearmente la velocità di apprendimento in base al numero di GPU (da 0,1 per 1 GPU a 6,4 per 64 GPU), mantenendo costante il numero di immagini per GPU a 256 (da un pacchetto di 256 immagini per 1 GPU a 16.384 per 64 GPU). I parametri di weight decay e momentum sono stati modificati man mano che aumentava il numero di GPU. Abbiamo utilizzato una formazione a precisione mista con il tipo di dati float16 per il forward pass e float32 per i gradienti, per accelerare i calcoli float16 supportati dalle GPU NVIDIA Tesla.
$ mpirun -np 16
-H server1:4,server2:4,server3:4,server4:4
-bind-to none -map-by slot
-mca pml ob1 -mca btl ^openib
python mxnet_imagenet_resnet50.pyConclusione
In questo articolo abbiamo esaminato un approccio scalabile all'apprendimento distribuito del modello utilizzando Apache MXNet e Horovod. Abbiamo dimostrato l'efficacia della scalabilità e l'efficienza economica rispetto all'approccio che utilizza un server di parametri su un dataset ImageNet, su cui è stata addestrata la modello ResNet50-v1. Inoltre, abbiamo illustrato i passaggi che puoi seguire per modificare uno script esistente per avviare l'apprendimento su più istanze utilizzando Horovod.
Se stai iniziando a lavorare con MXNet e l'apprendimento profondo, visita la pagina di installazione , per prima cosa compila MXNet. Ti consigliamo anche di leggere l'articolo , per iniziare.
Se hai già esperienza con MXNet e vuoi provare l'apprendimento distribuito con Horovod, dai un'occhiata alla , compilalo con MXNet e segui l'esempio o .
*il costo è calcolato sulla base di AWS per istanze EC2
Scopri di più sul corso
Fonte: habr.com
