Apache MXNet - Verteiltes Training

In diesem Kapitel geht es um das verteilte Training in Apache MXNet. Beginnen wir mit dem Verständnis der Berechnungsmodi in MXNet.

Berechnungsmodi

MXNet, eine mehrsprachige ML-Bibliothek, bietet seinen Benutzern die folgenden zwei Berechnungsmodi:

Imperativer Modus

Dieser Berechnungsmodus macht eine Schnittstelle wie die NumPy-API verfügbar. Verwenden Sie in MXNet beispielsweise den folgenden Imperativcode, um einen Tensor von Nullen sowohl auf der CPU als auch auf der GPU zu erstellen.

import mxnet as mx
tensor_cpu = mx.nd.zeros((100,), ctx=mx.cpu())
tensor_gpu= mx.nd.zeros((100,), ctx=mx.gpu(0))

Wie wir im obigen Code sehen, gibt MXNets den Ort an, an dem der Tensor gehalten werden soll, entweder in der CPU oder im GPU-Gerät. Im obigen Beispiel befindet es sich an Position 0. MXNet erreicht eine unglaubliche Auslastung des Geräts, da alle Berechnungen nicht sofort, sondern träge erfolgen.

Symbolischer Modus

Der imperative Modus ist zwar sehr nützlich, aber einer der Nachteile dieses Modus ist seine Steifigkeit, dh alle Berechnungen müssen im Voraus zusammen mit vordefinierten Datenstrukturen bekannt sein.

Andererseits zeigt der symbolische Modus ein Berechnungsdiagramm wie TensorFlow an. Es beseitigt den Nachteil der imperativen API, indem MXNet mit Symbolen oder Variablen anstelle von festen / vordefinierten Datenstrukturen arbeiten kann. Danach können die Symbole wie folgt als eine Reihe von Operationen interpretiert werden:

import mxnet as mx
x = mx.sym.Variable(“X”)
y = mx.sym.Variable(“Y”)
z = (x+y)
m = z/100

Arten von Parallelität

Apache MXNet unterstützt verteiltes Training. Es ermöglicht uns, mehrere Maschinen für ein schnelleres und effektives Training zu nutzen.

Im Folgenden finden Sie zwei Möglichkeiten, wie wir die Arbeitslast für das Training eines NN auf mehrere Geräte, CPU- oder GPU-Geräte verteilen können:

Datenparallelität

Bei dieser Art von Parallelität speichert jedes Gerät eine vollständige Kopie des Modells und arbeitet mit einem anderen Teil des Datensatzes. Geräte aktualisieren auch gemeinsam ein freigegebenes Modell. Wir können alle Geräte auf einer einzelnen Maschine oder auf mehreren Maschinen lokalisieren.

Modellparallelität

Es ist eine andere Art von Parallelität, die nützlich ist, wenn Modelle so groß sind, dass sie nicht in den Gerätespeicher passen. Bei der Modellparallelität wird verschiedenen Geräten die Aufgabe zugewiesen, verschiedene Teile des Modells zu lernen. Der wichtige Punkt hierbei ist, dass Apache MXNet derzeit Modellparallelität nur auf einem einzelnen Computer unterstützt.

Arbeiten von verteilten Schulungen

Die folgenden Konzepte sind der Schlüssel zum Verständnis der Funktionsweise verteilter Schulungen in Apache MXNet.

Arten von Prozessen

Prozesse kommunizieren miteinander, um das Training eines Modells durchzuführen. Apache MXNet hat die folgenden drei Prozesse:

Arbeiter

Die Aufgabe des Arbeiterknotens besteht darin, eine Schulung für eine Reihe von Schulungsmustern durchzuführen. Die Worker-Knoten ziehen Gewichte vom Server, bevor sie jeden Stapel verarbeiten. Die Worker-Knoten senden Farbverläufe an den Server, sobald der Stapel verarbeitet wurde.

Server

MXNet kann mehrere Server zum Speichern der Modellparameter und zur Kommunikation mit den Arbeitsknoten haben.

Planer

Die Rolle des Schedulers besteht darin, den Cluster einzurichten. Dazu gehört das Warten auf Nachrichten, die von jedem Knoten gesendet wurden und welchen Port der Knoten abhört. Nach dem Einrichten des Clusters informiert der Scheduler alle Prozesse über jeden anderen Knoten im Cluster. Dies liegt daran, dass die Prozesse miteinander kommunizieren können. Es gibt nur einen Scheduler.

KV Store

KV Stores steht für Key-ValueGeschäft. Es ist eine wichtige Komponente für das Training mit mehreren Geräten. Dies ist wichtig, da die Kommunikation von Parametern zwischen Geräten auf einem oder mehreren Computern über einen oder mehrere Server mit einem KVStore für die Parameter übertragen wird. Lassen Sie uns die Arbeitsweise von KVStore anhand der folgenden Punkte verstehen:

  • Jeder Wert in KVStore wird durch a dargestellt key und ein value.

  • Jedem Parameterarray im Netzwerk ist a zugeordnet key und auf die Gewichte dieses Parameterarrays wird verwiesen value.

  • Danach die Worker-Knoten pushFarbverläufe nach der Bearbeitung einer Charge. Sie auchpull Aktualisierte Gewichte vor der Verarbeitung einer neuen Charge.

Der Begriff des KVStore-Servers existiert nur während des verteilten Trainings und der verteilte Modus wird durch Aufrufen aktiviert mxnet.kvstore.create Funktion mit einem String-Argument, das das Wort enthält dist - -

kv = mxnet.kvstore.create(‘dist_sync’)

Verteilung der Schlüssel

Es ist nicht erforderlich, dass alle Server alle Parameterarrays oder -schlüssel speichern, sie sind jedoch auf verschiedene Server verteilt. Eine solche Verteilung von Schlüsseln auf verschiedene Server wird vom KVStore transparent behandelt, und die Entscheidung, auf welchem ​​Server ein bestimmter Schlüssel gespeichert wird, wird zufällig getroffen.

Wie oben erläutert, stellt KVStore sicher, dass bei jedem Ziehen des Schlüssels seine Anforderung an diesen Server gesendet wird, der den entsprechenden Wert hat. Was ist, wenn der Wert eines Schlüssels groß ist? In diesem Fall kann es von verschiedenen Servern gemeinsam genutzt werden.

Trainingsdaten teilen

Als Benutzer möchten wir, dass jeder Computer an verschiedenen Teilen des Datensatzes arbeitet, insbesondere wenn verteiltes Training im datenparallelen Modus ausgeführt wird. Wir wissen, dass wir einen Stapel von Stichproben, die vom Dateniterator für datenparalleles Training bereitgestellt werden, auf einen einzelnen Mitarbeiter aufteilen können, den wir verwenden könnenmxnet.gluon.utils.split_and_load Laden Sie dann jeden Teil des Stapels auf das Gerät, das ihn weiter verarbeitet.

Auf der anderen Seite müssen wir im Fall eines verteilten Trainings zu Beginn den Datensatz in unterteilen nverschiedene Teile, so dass jeder Arbeiter ein anderes Teil bekommt. Einmal erhalten, kann jeder Arbeiter dann verwendensplit_and_loadum diesen Teil des Datensatzes erneut auf verschiedene Geräte auf einem einzelnen Computer aufzuteilen. All dies geschieht durch einen Dateniterator.mxnet.io.MNISTIterator und mxnet.io.ImageRecordIter Es gibt zwei solche Iteratoren in MXNet, die diese Funktion unterstützen.

Gewichte aktualisieren

Zum Aktualisieren der Gewichte unterstützt KVStore die folgenden zwei Modi:

  • Die erste Methode aggregiert die Farbverläufe und aktualisiert die Gewichte mithilfe dieser Farbverläufe.

  • Bei der zweiten Methode aggregiert der Server nur Farbverläufe.

Wenn Sie Gluon verwenden, besteht die Möglichkeit, durch Übergeben zwischen den oben genannten Methoden zu wählen update_on_kvstoreVariable. Lassen Sie es uns verstehen, indem Sie das erstellentrainer Objekt wie folgt -

trainer = gluon.Trainer(net.collect_params(), optimizer='sgd',
   optimizer_params={'learning_rate': opt.lr,
      'wd': opt.wd,
      'momentum': opt.momentum,
      'multi_precision': True},
      kvstore=kv,
   update_on_kvstore=True)

Modi des verteilten Trainings

Wenn die KVStore-Erstellungszeichenfolge das Wort dist enthält, bedeutet dies, dass das verteilte Training aktiviert ist. Im Folgenden finden Sie verschiedene Modi für verteiltes Training, die mithilfe verschiedener KVStore-Typen aktiviert werden können:

dist_sync

Wie der Name schon sagt, bedeutet dies synchrones verteiltes Training. Dabei verwenden alle Mitarbeiter zu Beginn jeder Charge denselben synchronisierten Satz von Modellparametern.

Der Nachteil dieses Modus besteht darin, dass der Server nach jedem Stapel warten muss, um Farbverläufe von jedem Worker zu erhalten, bevor er die Modellparameter aktualisiert. Dies bedeutet, dass ein Absturz eines Arbeitnehmers den Fortschritt aller Arbeiter stoppen würde.

dist_async

Wie der Name schon sagt, bedeutet dies synchrones verteiltes Training. Dabei empfängt der Server Farbverläufe von einem Mitarbeiter und aktualisiert sofort seinen Speicher. Der Server verwendet den aktualisierten Speicher, um auf weitere Zugriffe zu reagieren.

Der Vorteil im Vergleich zu dist_sync modeist, dass ein Mitarbeiter, der die Verarbeitung eines Stapels beendet hat, die aktuellen Parameter vom Server abrufen und den nächsten Stapel starten kann. Der Arbeiter kann dies tun, auch wenn der andere Arbeiter die Verarbeitung der früheren Charge noch nicht abgeschlossen hat. Es ist auch schneller als der dist_sync-Modus, da es mehr Epochen dauern kann, bis es ohne Synchronisationskosten konvergiert.

dist_sync_device

Dieser Modus ist der gleiche wie dist_syncModus. Der einzige Unterschied besteht darin, dass auf jedem Knoten mehrere GPUs verwendet werdendist_sync_device aggregiert Farbverläufe und aktualisiert Gewichte auf der GPU, während dist_sync aggregiert Farbverläufe und aktualisiert Gewichte im CPU-Speicher.

Es reduziert die teure Kommunikation zwischen GPU und CPU. Deshalb ist es schneller alsdist_sync. Der Nachteil ist, dass es die Speichernutzung auf der GPU erhöht.

dist_async_device

Dieser Modus funktioniert genauso wie dist_sync_device Modus, aber im asynchronen Modus.