La traduzione dell'articolo è stata preparata in vista dell'inizio del corso
L'apprendimento distribuito su più istanze di calcolo ad alte prestazioni può ridurre il tempo di addestramento delle moderne reti neurali profonde su grandi volumi di dati da diverse settimane a ore o persino minuti, rendendo questa tecnica di apprendimento prevalente nelle questioni di utilizzo pratico del deep learning. Gli utenti devono comprendere come condividere e sincronizzare i dati su più istanze, il che influisce notevolmente sull'efficienza della scalabilità. Inoltre, gli utenti devono anche sapere come distribuire su più istanze uno script di addestramento che funziona su una singola istanza.
In questo articolo parleremo di un modo rapido e semplice di apprendimento distribuito utilizzando la libreria open source per il deep learning Apache MXNet e il framework di apprendimento distribuito Horovod. Dimostreremo visivamente i vantaggi del framework Horovod in termini di prestazioni e mostreremo come scrivere uno script di addestramento MXNet in modo che funzioni in modo distribuito con Horovod.
Che cos'è Apache MXNet
è un framework open source per il deep learning utilizzato per creare, addestrare e distribuire reti neurali profonde. MXNet astrae le complessità legate all'implementazione delle reti neurali, offre alte prestazioni e scalabilità, e fornisce API per linguaggi di programmazione popolari come , , , , , , e altro ancora.
Apprendimento distribuito in MXNet con un server dei parametri
utilizza un approccio con server dei parametri (parameter server). Utilizza 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 server-worker è la chiave per una scalabilità efficace. Se vi è solo un server dei parametri, può diventare un collo di bottiglia nel calcolo. Al contrario, se vengono utilizzati troppi server, la comunicazione "molti-a-molti" può saturare tutte le connessioni di rete.
Che cos'è Horovod
– un framework aperto per l'apprendimento profondo distribuito, sviluppato in Uber. Utilizza tecnologie efficaci 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 scala bene quando si lavorano con modelli di reti neurali approfondite. Attualmente supporta diversi framework di apprendimento automatico popolari, tra cui , Tensorflow, Keras e PyTorch.
Integrazione di MXNet e Horovod
MXNet si integra con Horovod tramite l'API di apprendimento distribuito definite in Horovod. Nella libreria Horovod, le API di comunicazione horovod.broadcast(), horovod.allgather() e horovod.allreduce() sono implementate utilizzando callback asincroni del motore MXNet, come parte del suo grafo di task. Così facendo, le dipendenze dei dati tra comunicazione e calcolo vengono gestite senza problemi dal motore MXNet, per evitare perdite di prestazioni dovute alla sincronizzazione. L'oggetto ottimizzatore distribuito, definito in Horovod horovod.DistributedOptimizer espande Ottimizzatore in MXNet in modo che invii le corrispondenti API di Horovod per l'aggiornamento distribuito dei parametri. Tutti questi dettagli di implementazione sono trasparenti per gli utenti finali.
Avvio veloce
Puoi iniziare rapidamente ad addestrare una piccola rete neurale convoluzionale sul set di dati MNIST utilizzando MXNet e Horovod sul tuo MacBook.
Per iniziare, installa mxnet e horovod da PyPI:
pip install mxnet
pip install horovodNota: Se ricevi un errore durante pip install horovod, potrebbe essere necessario aggiungere la variabile MACOSX_DEPLOYMENT_TARGET=10.vv, dove vv – è la versione della tua versione di MacOS, ad esempio, per MacOSX Sierra, sarà necessario scrivere MACOSX_DEPLOYMENT_TARGET=10.12 pip install horovod
Poi 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.pyCosì avvierai l'addestramento su due core del tuo processore. L'output sarà il 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 set di dati ImageNet su 64 GPU con otto istanze p3.16xlarge EC2, ognuno dei quali contiene 8 GPU NVIDIA Tesla V100 nel cloud AWS, abbiamo raggiunto una capacità di addestramento di 45000 immagini/sec (cioè il numero di campioni addestrati al secondo). L'addestramento si è concluso dopo 44 minuti con 90 epoche e la migliore accuratezza del 75,7%.
Abbiamo confrontato questo con l'addestramento distribuito di MXNet utilizzando l'approccio dei server di parametri su 8, 16, 32 e 64 GPU con un server con un solo parametro e un rapporto server-lavoratori 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, le linee riflettono l'efficienza di scalabilità (cioè il rapporto tra la capacità di throughput reale e quella ideale) sull'asse y a destra. Come potete vedere, la scelta del numero di server influisce sull'efficienza di scalabilità. Se il server dei parametri è uno, l'efficienza di scalabilità scende al 38% su 64 GPU. Per raggiungere la stessa efficienza di scalabilità di Horovod è necessario raddoppiare il numero di server rispetto al numero di lavoratori.

Figura 1. Confronto dell'addestramento distribuito utilizzando MXNet con Horovod e con un server di parametri
Nella Tabella 1 qui sotto abbiamo confrontato il costo finale dell'istanza durante l'esecuzione di esperimenti su 64 GPU. L'uso di MXNet insieme a Horovod fornisce la migliore capacità di throughput al costo più basso.

Tabella 1. Confronto dei costi tra Horovod e un server di parametri con un rapporto server-lavoratori di 2 a 1.
Passi per la riproduzione
Nei prossimi passaggi parleremo di come riprodurre il risultato dell'addestramento distribuito utilizzando MXNet e Horovod. Per saperne di più sull'addestramento 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'addestramento distribuito. Dovrai anche installare le librerie per l'addestramento 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 sull'API Gluon di MXNet può essere utilizzato come semplice modello. Le righe evidenziate in grassetto sono necessarie se hai già uno script di addestramento corrispondente. Ecco alcune modifiche critiche da apportare per l'addestramento con Horovod:
- Imposta il contesto in base al rango locale di Horovod (riga 8) per garantire che l'addestramento avvenga sulla corretta GPU.
- Trasmetti i parametri iniziali da un lavoratore a tutti (riga 18) per assicurarti che tutti i lavoratori inizino a lavorare con i medesimi parametri iniziali.
- Crea Horovod DistributedOptimizer (riga 25) per aggiornare i parametri in modo distribuito.
Per ottenere lo script completo, consulta gli esempi di 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: fissa una GPU da utilizzare 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 lavoratori per avviare l'addestramento distribuito utilizzando la direttiva MPI. In questo esempio, l'addestramento distribuito è avviato su quattro istanze con 4 GPU ciascuna, per un totale di 16 GPU nel cluster. Verrà utilizzato un ottimizzatore di discesa del gradiente stocastico (SGD) con i seguenti iperparametri:
- dimensione mini-batch: 256
- tasso di apprendimento: 0.1
- momentum: 0.9
- decadimento del peso: 0.0001
Man mano che si scala 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 il numero di immagini per GPU a 256 (da un batch di 256 immagini per 1 GPU a 16.384 per 64 GPU). I parametri di decadimento del peso e momentum sono stati modificati man mano che aumentava il numero di GPU. Abbiamo utilizzato l'addestramento a precisione mista con il tipo di dati float16 per il passaggio diretto e float32 per i gradienti, al fine di 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 dei modelli utilizzando Apache MXNet e Horovod. Abbiamo dimostrato l'efficacia della scalabilità e l'efficienza economica rispetto all'approccio basato sul server dei parametri su un set di dati ImageNet, su cui è stato addestrato il modello ResNet50-v1. Abbiamo anche descritto i passaggi che puoi seguire per modificare uno script esistente e avviare l'addestramento su più istanze utilizzando Horovod.
Se stai appena 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 a lavorare.
Se hai già lavorato con MXNet e vuoi provare l'apprendimento distribuito con Horovod, dai un'occhiata alla , compila con MXNet e segui l'esempio o .
*il costo è calcolato sulla base di AWS per le istanze EC2
Scopri di più sul corso
Fonte: habr.com
