Verteiltes Lernen mit Apache MXNet und Horovod

Die Übersetzung des Artikels wurde im Vorfeld des Starts des Kurses vorbereitet „Industrielles ML mit großen Daten“

Verteiltes Lernen auf mehreren leistungsstarken Berechnungseinheiten kann die Trainingszeit modernster tiefer neuronaler Netzwerke auf großen Datenmengen von mehreren Wochen auf Stunden oder sogar Minuten verkürzen, was diese Lerntechnik in Fragen der praktischen Anwendung des Deep Learnings dominant macht. Benutzer sollten verstehen, wie man Daten auf mehreren Einheiten teilt und synchronisiert, was sich wiederum erheblich auf die Skalierungseffizienz auswirkt. Darüber hinaus müssen Benutzer auch wissen, wie man ein Trainingsskript auf mehreren Einheiten bereitstellt, das auf einer Einheit funktioniert.

In diesem Artikel werden wir über einen schnellen und einfachen Weg des verteilten Lernens mit der Open-Source-Bibliothek für Deep Learning Apache MXNet und dem Framework für verteiltes Lernen Horovod sprechen. Wir werden die Vorteile des Horovod-Frameworks in Bezug auf die Leistung anschaulich zeigen und demonstrieren, wie man ein MXNet-Trainingsskript so schreibt, dass es verteilt mit Horovod funktioniert.

Was ist Apache MXNet

Apache MXNet – ein Open-Source-Framework für Deep Learning, das zur Erstellung, Schulung und Bereitstellung tiefer neuronaler Netzwerke verwendet wird. MXNet abstrahiert die Komplexität bei der Implementierung von neuronalen Netzwerken, bietet hohe Leistung und Skalierbarkeit und stellt APIs für gängige Programmiersprachen wie Python, C++, Clojure, Java, Julia, R, Scala und andere.

Verteiltes Lernen in MXNet mit Parameter Server

Das Standardmodul für verteiltes Lernen in MXNet verwendet den Ansatz des Parameter Servers. Es nutzt eine Reihe von Parameter-Servern, um Gradienten von jedem Worker zu sammeln, die Aggregation durchzuführen und die aktualisierten Gradienten zurück zu den Workern für die nächste Iteration der Optimierung zu senden. Das Festlegen des richtigen Verhältnisses von Servern zu Workern ist entscheidend für eine effiziente Skalierung. Wenn es nur einen Parameter-Server gibt, kann dieser zum Flaschenhals bei den Berechnungen werden. Umgekehrt, wenn zu viele Server verwendet werden, kann die „viele-zu-viele“-Verbindung alle Netzwerkverbindungen überlasten.

Was ist Horovod

Horovod – ein offenes Framework für verteiltes, tiefes Lernen, entwickelt von Uber. Es nutzt effektive Technologien für die Interaktion zwischen mehreren GPUs und Knoten, wie die NVIDIA Collective Communications Library (NCCL) und die Message Passing Interface (MPI), um die Parameter des Modells zwischen Workern zu verteilen und zu aggregieren. Es optimiert die Nutzung der Netzwerkbandbreite und skaliert gut beim Arbeiten mit Modellen tiefen neuronalen Netzen. Derzeit unterstützt es mehrere beliebte Frameworks für maschinelles Lernen, nämlich MXNet, Tensorflow, Keras und PyTorch.

Integration von MXNet und Horovod

MXNet integriert sich mit Horovod über die im Horovod definierten API für verteiltes Lernen. Im Horovod sind die Kommunikations-APIs horovod.broadcast(), horovod.allgather() und horovod.allreduce() über asynchrone Callback-Funktionen der MXNet-Engine implementiert, als Teil seines Aufgabenlayouts. Somit werden die Datenabhängigkeiten zwischen Kommunikation und Berechnungen von der MXNet-Engine einfach verarbeitet, um Leistungsverluste durch Synchronisierung zu vermeiden. Das Objekt des verteilten Optimierers, definiert in Horovod horovod.DistributedOptimizer erweitert Optimizer in MXNet, sodass er die entsprechenden APIs von Horovod für die verteilte Aktualisierung der Parameter aufruft. Alle diese Implementierungsdetails sind für die Endbenutzer transparent.

Schnellstart

Sie können schnell anfangen, ein kleines konvolutionales neuronales Netzwerk auf dem MNIST-Datensatz mit MXNet und Horovod auf Ihrem MacBook zu trainieren.
Um zu beginnen, installieren Sie mxnet und horovod von PyPI:

pip install mxnet
pip install horovod

Hinweis: Wenn Sie während der pip install horovodeine Fehlermeldung erhalten, müssen Sie möglicherweise die Variable MACOSX_DEPLOYMENT_TARGET=10.vv

vv – ist die Version Ihrer MacOS-Version, zum Beispiel, für MacOSX Sierra müssen Sie schreiben MACOSX_DEPLOYMENT_TARGET=10.12 pip install horovod

Installieren Sie dann OpenMPI von hier.

Laden Sie schließlich das Test-Skript mxnet_mnist.py von hier und führen Sie die folgenden Befehle im Terminal Ihres MacBook im Arbeitsverzeichnis aus:

mpirun -np 2 -H localhost:2 -bind-to none -map-by slot python mxnet_mnist.py

So starten Sie das Training auf zwei Kernen Ihres Prozessors. Die Ausgabe wird Folgendes sein:

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.870000

Leistungsdemonstration

Beim Training des ResNet50-v1-Modells auf dem ImageNet-Datensatz mit 64 GPUs und acht Instanzen p3.16xlarge EC2, von denen jede 8 GPU NVIDIA Tesla V100 in der AWS-Cloud enthält, haben wir eine Trainingsgeschwindigkeit von 45000 Bildern/Sekunde erreicht (d.h. die Anzahl der in einer Sekunde trainierten Proben). Das Training wurde nach 44 Minuten nach 90 Epochen mit einer besten Genauigkeit von 75.7% abgeschlossen.

Wir haben dies mit verteiltem Training von MXNet verglichen, das den Parameter-Server-Ansatz mit 8, 16, 32 und 64 GPUs verwendet, im Vergleich zu einem einzelnen Parameter-Server und einem Verhältnis von Servern zu Arbeitern von 1 zu 1 und 2 zu 1. Das Ergebnis sehen Sie in Abbildung 1 unten. Auf der y-Achse links spiegeln die Balken die Anzahl der Bilder für das Training pro Sekunde wider, die Linien zeigen die Effizienz der Skalierung (d.h. das Verhältnis der tatsächlichen Durchsatzrate zur idealen) auf der y-Achse rechts. Wie Sie sehen können, beeinflusst die Wahl der Anzahl der Server die Skalierungseffizienz. Wenn es einen einzelnen Parameter-Server gibt, sinkt die Skalierungseffizienz auf 38% bei 64 GPUs. Um die gleiche Skalierungseffizienz wie mit Horovod zu erreichen, muss die Anzahl der Server im Verhältnis zur Anzahl der Arbeiter verdoppelt werden.

Verteiltes Lernen mit Apache MXNet und Horovod
Abbildung 1. Vergleich des verteilten Trainings mit MXNet mit Horovod und einem Parameter-Server

In Tabelle 1 unten haben wir die Gesamtkosten des Instances bei Experimenten mit 64 GPUs verglichen. Die Verwendung von MXNet zusammen mit Horovod gewährleistet die beste Durchsatzrate zu den geringsten Kosten.

Verteiltes Lernen mit Apache MXNet und Horovod
Tabelle 1. Vergleich der Kosten zwischen Horovod und einem Parameter-Server mit einem Verhältnis von Servern zu Arbeitern von 2 zu 1.

Schritte zur Reproduktion

In den nächsten Schritten erklären wir, wie das Ergebnis des verteilten Trainings mit MXNet und Horovod reproduziert werden kann. Um mehr über das verteilte Training mit MXNet zu erfahren, lesen Sie diesen Beitrag.

Schritt 1

Erstellen Sie einen Cluster homogener Instances mit MXNet Version 1.4.0 oder höher und Horovod Version 0.16.0 oder höher, um verteiltes Training zu verwenden. Sie müssen auch die Bibliotheken für das Training auf GPU installieren. Für unsere Instances haben wir Ubuntu 16.04 Linux, mit GPU-Treiber 396.44, CUDA 9.2, cuDNN-Bibliothek 7.2.1, NCCL-Communicator 2.2.13 und OpenMPI 3.1.1 ausgewählt. Alternativ können Sie auch Amazon Deep Learning AMI, wo diese Bibliotheken bereits vorinstalliert sind.

Schritt 2

Fügen Sie Ihrem Trainings-Skript MXNet die Möglichkeit hinzu, mit der API Horovod zu arbeiten. Das nachfolgende Skript basierend auf der MXNet Gluon API kann als einfaches Template verwendet werden. Die fett gedruckten Zeilen sind erforderlich, wenn Sie bereits über ein entsprechendes Trainings-Skript verfügen. Hier sind einige kritische Änderungen, die für das Training mit Horovod vorgenommen werden müssen:

  • Setzen Sie den Kontext gemäß dem lokalen Rang von Horovod (Zeile 8), um sicherzustellen, dass das Training auf dem richtigen Grafikprozessor ausgeführt wird.
  • Übertragen Sie die Startparameter von einem Worker an alle (Zeile 18), um sicherzustellen, dass alle Worker mit denselben Startparametern beginnen.
  • Erstellen Sie Horovod DistributedOptimizer (Zeile 25), um die Parameter verteilt zu aktualisieren.

Um das vollständige Skript zu erhalten, beachten Sie die Beispiele von Horovod-MXNet MNIST und ImageNet.

1  import mxnet as mx
2  import horovod.mxnet as hvd
3
4  # Horovod: Horovod initialisieren
5  hvd.init()
6
7  # Horovod: eine GPU für den lokalen Rang festlegen
8  context = mx.gpu(hvd.local_rank())
9
10 # Modell aufbauen
11 model = ...
12
13 # Parameter initialisieren
14 model.initialize(initializer, ctx=context)
15 params = model.collect_params()
16
17 # Horovod: Parameter übertragen
18 hvd.broadcast_parameters(params, root_rank=0)
19
20 # Optimierer erstellen
21 optimizer_params = ...
22 opt = mx.optimizer.create('sgd', **optimizer_params)
23
24 # Horovod: Optimierer mit DistributedOptimizer umwickeln
25 opt = hvd.DistributedOptimizer(opt)
26
27 # Trainer und Verlustfunktion erstellen
28 trainer = mx.gluon.Trainer(params, opt, kvstore=None)
29 loss_fn = ...
30
31 # Modell trainieren
32 for epoch in range(num_epoch):
33    ...

Schritt 3

Treten Sie in einen der Worker ein, um das verteilte Training mit dem MPI-Befehl zu starten. In diesem Beispiel wird das verteilte Training auf vier Instanzen mit 4 GPUs in jeder Instanz durchgeführt, was zu insgesamt 16 GPUs im Cluster führt. Es wird ein stochastischer Gradientabstieg (SGD) mit den folgenden Hyperparametern verwendet:

  • mini-batch Größe: 256
  • Lernrate: 0.1
  • Momentum: 0.9
  • Gewichtsverfall: 0.0001

Beim Skalieren von einem GPU auf 64 GPUs haben wir die Lernrate entsprechend der Anzahl der GPUs linear skaliert (von 0,1 für 1 GPU bis 6,4 für 64 GPUs), während wir die Anzahl der Bilder, die auf jede GPU fallen, bei 256 belassen haben (von einem Batch mit 256 Bildern für 1 GPU bis 16.384 für 64 GPUs). Die Parameter für Gewichtverfall und Momentum wurden angepasst, während die Anzahl der GPUs zunahm. Wir haben gemischte Präzision beim Training verwendet, mit dem Datentyp float16 für den Vorwärtsdurchlauf und float32 für die Gradienten, um die float16 Berechnungen zu beschleunigen, die von NVIDIA Tesla GPUs unterstützt werden.

$ 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.py

Fazit

In diesem Artikel haben wir einen skalierbaren Ansatz für das verteilte Training von Modellen unter Verwendung von Apache MXNet und Horovod betrachtet. Wir haben die Effizienz der Skalierung und die wirtschaftliche Effizienz im Vergleich zu einem Parameter-Server-Ansatz anhand des ImageNet-Datensatzes, auf dem das Modell ResNet50-v1 trainiert wurde, demonstriert. Außerdem haben wir die Schritte aufgezeigt, mit denen Sie ein bestehendes Skript ändern können, um das Training auf mehreren Instanzen mit Horovod zu starten.

Wenn Sie gerade erst mit MXNet und Deep Learning anfangen, gehen Sie zur Installationsseite MXNe, um zuerst MXNet zu installieren. Wir empfehlen Ihnen auch, den Artikel MXNet in 60 Minuten, zu lesen, um loszulegen.

Wenn Sie bereits mit MXNet gearbeitet haben und verteiltes Training mit Horovod ausprobieren möchten, schauen Sie auf die Installationsseite von Horovod, installieren Sie es mit MXNet und folgen Sie dem Beispiel MNIST oder ImageNet.

*Die Kosten werden auf der Grundlage von Stundenpreisen AWS für EC2-Instanzen

Erfahren Sie mehr über den Kurs „Industrielles ML mit großen Daten“

Quelle: habr.com

60GB SSD 8Gb DDR4