Der Artikel wurde im Vorfeld des Kurses erstellt
Verteiltes Lernen auf mehreren leistungsstarken Recheninstanzen kann die Trainingszeit moderner tiefer neuronaler Netze bei großen Datenmengen von mehreren Wochen auf Stunden oder sogar Minuten verkürzen. Diese Technik des Lernens wird daher in der praktischen Anwendung des tiefen Lernens zunehmend bevorzugt. Benutzer sollten verstehen, wie sie Daten auf mehreren Instanzen teilen und synchronisieren können, was wiederum einen erheblichen Einfluss auf die Effizienz der Skalierung hat. Darüber hinaus müssen Benutzer wissen, wie sie ein Trainingsskript auf mehreren Instanzen bereitstellen, das auf einer einzelnen Instanz funktioniert.
In diesem Artikel besprechen wir eine schnelle und einfache Methode für verteiltes Lernen unter Verwendung der Open-Source-Bibliothek für Deep Learning Apache MXNet und dem verteilten Lern-Framework Horovod. Wir werden die Vorteile des Horovod-Frameworks hinsichtlich der Leistung anschaulich darstellen und zeigen, wie man ein Trainingsskript für MXNet so schreibt, dass es verteilt mit Horovod funktioniert.
Was ist Apache MXNet
ist ein Open-Source-Framework für Deep Learning, das zur Erstellung, Schulung und Bereitstellung tiefer neuronaler Netzwerke verwendet wird. MXNet abstrahiert die Komplexität im Zusammenhang mit der Implementierung neuronaler Netzwerke, bietet hohe Leistung und Skalierbarkeit und bietet APIs für populäre Programmiersprachen wie , , , , , , und andere.
Verteiltes Lernen in MXNet mit Parameter-Server
verwendet einen Parameter-Server-Ansatz. Dabei nutzt er eine Vielzahl von Parameter-Servern, um Gradienten von jedem Worker zu sammeln, diese zu aggregieren und die aktualisierten Gradienten an die Worker für die nächste Optimierungsiteration zurückzusenden. Die richtige Balance zwischen Servern und Workern ist entscheidend für eine effiziente Skalierung. Ist nur ein Parameter-Server vorhanden, könnte dieser zum Engpass bei den Berechnungen werden. Umgekehrt kann zu viele Servern eine Überlastung der Netzwerkverbindungen durch die "Viele-zu-viele"-Kommunikation verursachen.
Was ist Horovod
– ein offenes Framework für verteiltes Deep Learning, das bei Uber entwickelt wurde. Es nutzt effiziente Technologien für die Interaktion zwischen mehreren GPUs und Knoten, wie die NVIDIA Collective Communications Library (NCCL) und das Message Passing Interface (MPI), um die Parameter des Modells zwischen den Workern zu verteilen und zu aggregieren. Es optimiert die Nutzung der Netzwerkbandbreite und skaliert gut mit Deep-Learning-Modellen. Derzeit unterstützt es mehrere populäre Machine-Learning-Frameworks, nämlich , Tensorflow, Keras und PyTorch.
Integration von MXNet und Horovod
MXNet integriert sich mit Horovod über die im Horovod definierten APIs für das verteilte Lernen. In Horovod sind die Kommunikations-APIs horovod.broadcast(), horovod.allgather() und horovod.allreduce() über asynchrone Callbacks der MXNet-Engine implementiert, als Teil seines Task-Diagramms. So können Datenabhängigkeiten zwischen Kommunikation und Berechnungen vom MXNet-Engine problemlos verarbeitet werden, um Leistungseinbußen durch Synchronisation zu vermeiden. Das in Horovod definierte Objekt horovod.DistributedOptimizer erweitert Optimizer In MXNet wird es so konfiguriert, dass es die entsprechenden Horovod-APIs für die verteilte Aktualisierung von Parametern aufruft. Diese Implementierungsdetails sind für die Endbenutzer transparent.
Schnellstart
Sie können schnell damit beginnen, ein kleines Convolutional Neural Network mit dem MNIST-Datensatz mithilfe von MXNet und Horovod auf Ihrem MacBook zu trainieren.
Um zu beginnen, installieren Sie mxnet und horovod aus PyPI:
pip install mxnet
pip install horovodHinweis: Wenn Sie während pip install horovodauf einen Fehler stoßen, müssen Sie möglicherweise die Variable hinzufügen MACOSX_DEPLOYMENT_TARGET=10.vv, wobei vv – dies ist die Version Ihres MacOS, beispielsweise für MacOSX Sierra sollten Sie schreiben MACOSX_DEPLOYMENT_TARGET=10.12 pip install horovod
Installieren Sie anschließend OpenMPI .
Laden Sie abschließend das Testskript herunter mxnet_mnist.py 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.pySo starten Sie das Training auf zwei Kernen Ihrer CPU. Das Ergebnis wird Folgendes sein:
INFO:root:Epoch[0] Batch [0-50] Geschwindigkeit: 2248.71 Proben/Sekunde Genauigkeit=0.583640
INFO:root:Epoch[0] Batch [50-100] Geschwindigkeit: 2273.89 Proben/Sekunde Genauigkeit=0.882812
INFO:root:Epoch[0] Batch [50-100] Geschwindigkeit: 2273.39 Proben/Sekunde Genauigkeit=0.870000Leistungsdemonstration
Beim Training des ResNet50-v1 Modells mit dem ImageNet-Datensatz auf 64 GPUs mit acht Instanzen, p3.16xlarge EC2, wobei jede 8 NVIDIA Tesla V100 GPUs in der AWS Cloud enthält, haben wir eine Trainingsgeschwindigkeit von 45.000 Bildern/Sekunde erreicht (d.h. die Anzahl der trainierten Samples pro Sekunde). Das Training wurde nach 44 Minuten und 90 Epochen mit einer besten Genauigkeit von 75,7% abgeschlossen.
Wir haben dies mit verteiltem Training in MXNet verglichen, wobei Parameter-Server mit 8, 16, 32 und 64 GPUs sowie ein einzelner Server mit einem Parameter und einem Verhältnis von Servern zu Workern von 1 zu 1 bzw. 2 zu 1 verwendet wurden. Das Ergebnis sehen Sie in Abbildung 1 unten. Auf der linken Y-Achse spiegeln die Balken die Anzahl der Bilder wider, die pro Sekunde zum Training verwendet werden, während die Linien die Skalierungseffizienz (d.h. das Verhältnis der tatsächlichen Bandbreite zur idealen) auf der rechten Y-Achse darstellen. Wie Sie sehen können, hat die Wahl der Anzahl der Server Einfluss auf die Skalierungseffizienz. Wenn der Parameter-Server einzelnd ist, sinkt die Skalierungseffizienz auf 38% bei 64 GPUs. Um eine ähnliche Skalierungseffizienz wie mit Horovod zu erreichen, muss die Anzahl der Server im Verhältnis zur Anzahl der Worker verdoppelt werden.

Abbildung 1. Vergleich des verteilten Lernens mit MXNet unter Verwendung von Horovod und Parameterserver.
In der Tabelle 1 unten vergleichen wir die Gesamtkosten eines Instanzbetriebs bei Experimenten auf 64 GPUs. Die Verwendung von MXNet zusammen mit Horovod bietet die beste Durchsatzrate bei den geringsten Kosten.

Tabelle 1. Vergleich der Kosten zwischen Horovod und Parameterserver mit einem Verhältnis von Servern zu Workern von 2 zu 1.
Schritte zur Reproduktion
In den folgenden Schritten erklären wir, wie Sie das Ergebnis des verteilten Lernens mit MXNet und Horovod reproduzieren können. Um mehr über verteiltes Lernen mit MXNet zu erfahren, lesen Sie .
Schritt 1
Erstellen Sie einen Cluster homogener Instanzen mit MXNet Version 1.4.0 oder höher und Horovod Version 0.16.0 oder höher, um verteilt zu lernen. Sie müssen auch die Bibliotheken für das Training auf GPU installieren. Für unsere Instanzen haben wir Ubuntu 16.04 Linux gewählt, mit GPU-Treiber 396.44, CUDA 9.2, cuDNN-Bibliothek 7.2.1, NCCL-Communicator 2.2.13 und OpenMPI 3.1.1. Alternativ können Sie auch , wo diese Bibliotheken bereits vorinstalliert sind.
Schritt 2
Fügen Sie Ihrem Trainingsskript MXNet die Möglichkeit hinzu, mit der Horovod-API zu arbeiten. Das nachfolgende Skript basierend auf der MXNet Gluon API kann als einfacher Rahmen verwendet werden. Die fettgedruckten Zeilen sind erforderlich, wenn Sie bereits über ein entsprechendes Trainingsskript verfügen. Hier sind einige kritische Änderungen, die vorgenommen werden müssen, um mit Horovod zu trainieren:
- Setzen Sie den Kontext gemäß dem lokalen Rang von Horovod (Zeile 8), um sicherzustellen, dass das Training auf der richtigen GPU durchgeführt wird.
- Übertragen Sie die Anfangsparameter von einem Worker an alle (Zeile 18), um sicherzustellen, dass alle Worker mit den gleichen Anfangswerten starten.
- Erstellen Sie Horovod DistributedOptimizer (Zeile 25), um die Parameter verteilt zu aktualisieren.
Um das vollständige Skript zu erhalten, sehen Sie sich die Beispiele für Horovod-MXNet an. und .
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 verpacken
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 einem der Worker bei, um das verteilte Training mit der MPI-Direktive zu starten. In diesem Beispiel wird das verteilte Training auf vier Instanzen mit jeweils 4 GPUs und insgesamt 16 GPUs im Cluster ausgeführt. Es wird der Stochastic Gradient Descent (SGD) Optimierer mit den folgenden Hyperparametern verwendet:
- Mini-Batch-Größe: 256
- Lernrate: 0,1
- Momentum: 0,9
- Gewichtsabbau: 0,0001
Beim Skalieren von einem GPU auf bis zu 64 GPUs haben wir die Trainingsgeschwindigkeit linear entsprechend der Anzahl der GPUs skaliert (von 0,1 für 1 GPU bis 6,4 für 64 GPUs), während wir die Anzahl der Bilder pro GPU konstant bei 256 gehalten haben (von einem Batch mit 256 Bildern für 1 GPU bis 16.384 für 64 GPUs). Die Parameter Weight Decay und Momentum wurden entsprechend der Anzahl der GPUs angepasst. Wir haben gemischte Präzision beim Training eingesetzt, wobei der Datentyp float16 für die Vorwärtsberechnung und float32 für die Gradienten verwendet wurde, um die von NVIDIA Tesla GPUs unterstützten Berechnungen in float16 zu beschleunigen.
$ 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.pyFazit
In diesem Artikel haben wir einen skalierbaren Ansatz für das verteilte Training von Modellen unter Verwendung von Apache MXNet und Horovod untersucht. Wir haben die Effizienz der Skalierung und die Kostenoptimierung im Vergleich zu einem Ansatz mit einem Parameter-Server auf dem Datensatz ImageNet gezeigt, auf dem das Modell ResNet50-v1 trainiert wurde. Zudem haben wir die Schritte aufgezeigt, mit denen Sie ein bestehendes Skript anpassen können, um das Training auf mehreren Instanzen mithilfe von Horovod zu starten.
Wenn Sie neu in der Arbeit mit MXNet und tiefem Lernen sind, besuchen Sie die Installationsseite. , um zunächst MXNet zusammenzubauen. Wir empfehlen außerdem dringend, den Artikel zu lesen, , um den Einstieg zu erleichtern.
Falls Sie bereits mit MXNet gearbeitet haben und verteiltes Lernen mit Horovod ausprobieren möchten, besuchen Sie die , bauen Sie es zusammen mit MXNet und folgen Sie dem Beispiel. oder .
*Die Kosten werden auf Basis der von AWS für EC2-Instanzen berechnet.
Erfahren Sie mehr über den Kurs
Quelle: habr.com
