Der Artikel wurde von Rakshith Vasudev & John Lockman, HPC AI Innovation Lab, im Oktober 2019 verfasst.
Wie bereits erwähnt, handelt es sich bei CheXNet um ein KI-Assistentenmodell für Radiologen, das DenseNet verwendet, um bis zu 14 Pathologien auf einem Thorax-Röntgenbild zu identifizieren. Es wurden mehrere Ansätze untersucht, um das Training eines Modells zu skalieren, damit es genauso gut oder sogar besser als das ursprüngliche CheXNet-121 mit ResNet-50 ist. Dabei wurden vielversprechende Ergebnisse in Bezug auf Skalierbarkeit und höhere Trainingsgenauigkeit (positives AUROC) erzielt. Die Autoren konnten Skalierbarkeit auf CPU-Systemen nachweisen, wir sind aber daran interessiert, die Parallelität von GPUs zu nutzen, um den Trainingsprozess zu beschleunigen. In diesem Artikel werden die Best Practices zum Erreichen einer maximalen Performance beim verteilten Scale-out-Training von CheXNet unter Verwendung von NVIDIA V100-SXM2-GPUs auf Dell EMC C4140-Servern beschrieben. Der Dell EMC PowerEdge C4140 bietet mit vier NVIDIA V100-GPUs in SXM2-Konfiguration sowohl Dichte als auch Performance.
Hardwarekonfiguration: | Softwarekonfiguration: |
---|---|
|
|
Während neue Rechengeräte (z. B. GPUs und TPUs) es ermöglichen, neuronale Netzwerke immer schneller zu trainieren, kann es bei der CPU-Verarbeitung zu Engpässen kommen. Die tf.data-API bietet Nutzern Bausteine für den Entwurf von Eingabe-Pipelines, die die CPU effektiv nutzen und jeden Schritt des ETL-Prozesses optimieren.
Um einen Trainingsschritt durchzuführen, müssen zunächst die Trainingsdaten extrahiert und transformiert und dann in ein Modell eingespeist werden, das auf einem Accelerator ausgeführt wird. In einer naiven synchronen Implementierung befindet sich der Accelerator jedoch im Leerlauf, während die CPU die Daten vorbereitet. Genauso umgekehrt, während der Accelerator das Modell trainiert, befindet sich die CPU im Leerlauf. Die Dauer des Trainingsschritts ist daher die Summe der CPU-Vorverarbeitungszeit und der Accelerator-Trainingszeit.
Mit Pipelining überlappen sich die Vorverarbeitung und die Modellausführung eines Trainingsschritts. Während der Accelerator den Trainingsschritt N durchführt, bereitet die CPU die Daten für Schritt N+1 vor. Auf diese Weise wird die Dauer des Trainingsschritts auf das Maximum (im Gegensatz zur Summe) des Trainings und der Zeit für das Extrahieren und Transformieren der Daten reduziert.
Ohne Pipelining bleiben CPU und GPU/TPU einen Großteil der Zeit im Leerlauf:
Abb. 1: Durch die sequenzielle Ausführung bleibt die GPU häufig im Leerlauf.
Mit Pipelining verringert sich die Leerlaufzeit erheblich:
Abb. 2: Mit Pipelining überlappen sich CPU- und GPU-Auslastung, wodurch die GPU-Auslastung erhöht wird.
Die tf.data-API bietet über die tf.data.Dataset.prefetch-Transformation einen Software-Pipelining-Mechanismus, der verwendet werden kann, um die Zeit, zu der Daten erzeugt werden, von der Zeit, zu der sie verbraucht werden, zu entkoppeln. Insbesondere verwendet die Transformation einen Hintergrund-Thread und einen internen Puffer, um Elemente aus dem Eingabe-Datensatz vor dem angeforderten Zeitpunkt vorab abzurufen.
Weitere Informationen finden Sie hier: https://www.tensorflow.org/guide/performance/datasets.
Wenn die von Tensorflow bereitgestellten Richtlinien befolgt werden, kann eine Daten-Pipeline wie die folgende erstellt werden (alter Ansatz):
https://github.com/dellemc-hpc-ai/code-examples/blob/master/cheXNet-snippets/old_approach.py.
Bei diesem Ansatz, der auch als alter Ansatz bezeichnet wird, führt die TF-Datenpipeline Folgendes aus (vorausgesetzt, der Datensatz des Thorax-Röntgenbilds ist eine Sequenz von TFRecords):
Es handelt sich hierbei jedoch nicht um den leistungsstärksten Code. Er führt zu Stillständen und häufigen GPU-Auslastungen von 0 %. Im Grunde genommen werden die Accelerator nicht effektiv genutzt.
Um die TF-Daten-Pipeline korrekt einzurichten, folgen wir dem Ansatz der offiziellen Tensorflow-Modelle, insbesondere dem für ResNet. Der Unterschied zwischen dem alten und dem neuen Ansatz besteht darin, wie die Daten-Pipeline eingerichtet wird, bevor sie in das Modell eingespeist wird.
So sieht der neue Ansatz aus:
https://github.com/dellemc-hpc-ai/code-examples/blob/master/cheXNet-snippets/new_approach.py.
Der offizielle TensorFlow-Modellansatz, der auch als neuer Ansatz bezeichnet wird, sieht wie folgt aus:
Nachfolgend finden Sie einen Vergleich der Performance des alten und neuen Ansatzes anhand der offiziellen TF-Modelle.
Abb. 3: Mit dem neuen Ansatz ist eine nahezu lineare Skalierung zu erwarten.
Wie zu sehen ist, kommt es beim alten Ansatz zu einer erheblichen Performanceeinbuße und es gibt überhaupt keine Skalierungsmöglichkeit. GPUs würden häufig nur wenig bis gar keine Auslastung aufweisen, was zu einer Flatline-Performance führt. Wenn die Berechnung auf einer GPU effizienter gemacht wird, wird auch die Berechnung auf mehreren GPUs auf mehreren Nodes effizienter, wenn die Kommunikation optimal gehandhabt wird.
Die parallele Vorverarbeitung der CPUs, der Vorabruf der verarbeiteten Daten aus dem Arbeitsspeicher und die komplexe Matrix-Multiplikation der GPUs mit schneller Kommunikation sind weitere Aspekte, die diesen neuen Ansatz für die Skalierung von Multinodes attraktiver machen.
Die Umgebung, in der Ihre Jobs ausgeführt werden, ist genauso wichtig wie die Jobs selbst, da die richtigen Bibliotheken/Module sich auf die Trainingsperformance auswirken. Auch die neuesten CUDA-bezogenen Bibliotheken können dazu beitragen, die Performance zu verbessern.
Befolgen Sie dieses Tutorial für die Installation, wenn Sie keine passende Umgebung eingerichtet haben.
MPI ist eine Kommunikationsbibliothek, die Horovod bei der Verteilung von Jobs unterstützt. Es wurden verschiedene Bindungs- und Zuordnungsparameteroptionen untersucht und der beste Parameter für den C4140 war die Zuordnung nach Sockel. Die empfohlene Einrichtung ist wie folgt:mpirun --map-by socket -np x python pyfile.py --pyoptions
Wenn mehr als ein Prozess auf einer GPU ausgeführt wird, kann es zu GPU-Ressourcenkonflikten kommen. Es wird GPU-Speicher verbraucht und effektiv werden nicht mehr Bilder pro Stapel eingebunden, was zu einer Beeinträchtigung der GPU-Performance führt. Tensorflow 1.13.1 wurde zwar untersucht, aber zu diesem Zeitpunkt schien ein Fehler vorhanden zu sein. Es wurde mehr als ein Prozess pro GPU gestartet.
Zusammenfassung: