Sent from Hauptstadt!

ein Blog für den geneigten Leser

TensorFlow 2 mit GPU Unterstützung

Tags: ,

Kategorie Software Engineering | 4 Kommentare »

Ich wollte ausprobieren, welchen Unterschied es beim Training eines neuronalen Netzwerk macht, wenn man die Rechenarbeit auf die Grafikkarte auslagert. Das endete in einer stundenlangen Installationsorgie gigabytegroßer Frameworks und war am Ende viel einfacher als gedacht. Ach und die Ergebnisse des Performance Tests waren extrem überraschend.

Beispiel: Neuronales Netz für Erkennen handgeschriebener Ziffern

Neuronale Netzwerke werden durch riesige Matrizen (mit durchaus mehreren hunderttausend Spalten und mehr) dargestellt. Auf diesen Matrizen müssen mathematische Operationen wie Skalarprodukt, Invertierung, usw. effizient ausgeführt werden. Für diese Art von Operationen sind Grafikkarten im Gegensatz zu normalen Desktop CPUs optimiert, weil Matrizenrechnung auch bei der Berechnung von 3D Szenen essentiell ist.

Ich wollte deshalb testen, wie stark sich das Training eines neuronalen Netzwerks auf meinem Arbeitsrechner beschleunigen lässt, wenn ich meine Grafikkarte in die Rechenarbeit einbeziehe.

In meinem Arbeitsrechner, der nicht mehr ganz neu ist, steckt ein

  • Quadcore Intel i5-6400 mit 2,7GHz
  • 32GB RAM und
  • eine Grafikkarte mit NVIDEA GeForce GTX 960 und 4GB Grafikspeicher.

Für das Training der 25 Epochen des folgenden kleinen neuronalen Netzwerks benötigt mein Rechner rund 60 Sekunden, wenn die GPU Unterstützung nicht aktiviert ist.

import tensorflow as tf

config = tf.compat.v1.ConfigProto()

# dynamically grow the memory used on the GPU
config.gpu_options.allow_growth = True
config.log_device_placement = True
sess = tf.compat.v1.Session(config=config)
tf.compat.v1.keras.backend.set_session(sess)

num_classes = 10
img_rows = 28
img_cols = 28
num_channels = 1
input_shape = (img_rows, img_cols, num_channels)

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train = x_train / 255.0
x_test = x_test / 255.0

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(128, activation='relu'))
model.add(tf.keras.layers.Dense(num_classes, activation='softmax'))

model.compile(optimizer='sgd',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
model.fit(x_train, y_train, epochs=25, verbose=1, validation_data=(x_test, y_test))

Das ist ein klassisches Beispiel für ein neuronales Netzwerk. Auf Basis der MNIST Sammlung von 70.000 Bildern handgeschriebener Ziffern wird ein Netzwerk trainiert, welches handgeschriebene Ziffern automatisiert erkennt. Mit der im obigen Beispiel verwendeten Architektur und Parametern erreicht mein Netzwerk immerhin eine Erkennungsrate von knapp 97%.

NVIDIA CUDA und TensorFlow unter Windows 10

Für die Ausführung nutze ich die „base“ Umgebung von Anaconda unter Windows 10 Pro 64Bit. Das neuronale Netzwerk im obigen Beispiel ist mittels des Framework TensorFlow implementiert. In Anaconda sind bereits sehr viele Python Bibliotheken für maschinelles Lernen enthalten, nicht aber TensorFlow. In der Basisumgebung von Anaconda lässt sich TensorFlow via pip installieren:

pip install tensorflow

Aktuell installiert pip die Version 2.1 von TensorFlow. Die installierte Version ist bereits mit GPU Unterstützung kompiliert. Beim Start des Programms warnt TensorFlow aber, dass es eine Reihe von Bibliotheken nicht finden kann und meine Grafikkarte sich nicht nutzen lässt.

Damit es funktioniert, müssen mehrere Komponenten in folgender Reihenfolge installiert werden:

  • Visual Studio Community 2019
  • NVIDIA CUDA Toolkit in Version 10.1 (2,4GB Download)
  • NVIDIA cuDNN Bibliothek Version 7.5 (0,4GB Download)

Ich bin mir nicht sicher, ob Visual Studio Community 2019 wirklich benötigt wird. Allerdings ist es hilfreich, da ich damit die im NVIDIA CUDA Toolkit enthaltenen C++ Code Beispiele direkt kompilieren und ausführen kann. Damit sehe ich, ob der Zugriff auf meine Grafikkarte mittels CUDA klappt, bevor ich die Komplexität dann weiter mit Anaconda und TensorFlow erhöhe.

Das NVIDIA CUDA Toolkit ist eine große Werkzeugsammlung, um Programmen den Zugriff auf NVIDIA GPUs zu ermöglichen. Mit diesem Framework und der umfassenden Integration in verschiedene Frameworks für maschinelles Lernen wie TensorFlow hat NVIDIA ein Alleinstellungsmerkmal für seine Grafikchips im Bereich KI geschaffen.

Weiterhin benötige ich noch die NVIDIA cuDNN Bibliothek, welche ich erst nach kostenloser Registrierung herunterladen konnte. Die Installation dieser Bibliothek ist sehr krude. Die einzelnen Bestandteile wie DLL und C++ Header Dateien müssen manuell in die entsprechenden Verzeichnisse des CUDA Toolkits kopiert werden. Hier ist es enorm wichtig, sich genau an die Installationsanweisungen von NVIDIA zu halten, damit am Ende auch alles zusammenpasst und sich gegenseitig findet.

Eine weitere Stolperfalle ist, dass die Versionen der einzelnen Komponenten zueinander passen müssen. Bei TensorFlow gibt es eine Dokumentation, welche Versionskombinationen von TensorFlow, NVIDIA CUDA, NVIDIA cuDNN und Visual Studio getestet wurden, um TensorFlow manuell zu kompilieren. Das kann unnötige Downloads ersparen. Hätte ich das nur vorher gewusst…

Mit dem Raussuchen der entsprechenden Bestandteile, Installation und Konfiguration gehen Stunden ins Land. Nachdem ich alle Stolperfallen gemeistert hatte, habe ich eine wesentlich einfachere Variante gefunden, die nur wenige Minuten beansprucht.

TensorFlow und NVIDIA via Anaconda installieren

Ich hatte auch gleich zu Beginn gesucht, ob sich die von TensorFlow für GPU Unterstützung benötigten Bibliotheken und Toolkits nicht per Anaconda installieren lassen, aber auf der offiziellen TensorFlow Seite zur Installation mit GPU Unterstützung ist dieser Weg nicht erwähnt. Vermutlich ist folgender Ansatz auch eher für kleine Testinstallationen geeignet als für ernsthafte Setups.

Ausgangspunkt ist wiederum eine aktuelle Anaconda Installation. In dieser erstellt man entweder per Kommandozeile oder Anaconda Navigator eine neue Umgebung und installiert in dieser das Metapaket tensorflow-gpu, das alle benötigten Abhängigkeiten referenziert:

conda create --name tf_gpu tensorflow-gpu 

Warum kann die offizielle TensorFlow Seite nicht zumindest einen kleinen Hinweis auf diesen Zeitsparer (Quelle) enthalten?

Übrigens, in Windows PowerShell misst man die Ausführungszeit mittels:

Measure-Command {python run.py}

Negative Beschleunigung durch GPU Unterstützung

Und wie hoch ist nun die Beschleunigung durch die GPU Unterstützung? Kann ich vielleicht sogar die Geschwindigkeit verdoppeln? Tatsächlich ist eine Verdoppelung der Geschwindigkeit drin, allerdings mit negativem Vorzeichen. Während das Training meines neuronalen Netzwerks ohne GPU Unterstützung rund 60 Sekunden benötigt, sind es mit GPU Unterstützung 116 Sekunden :-(

Während des Trainings wird meine GPU nur zu 10% ausgelastet. Es steht zu vermuten, dass meine Grafikkate einfach zu alt ist oder zu wenig Speicher hat oder das Training mit Consumer Grafikkarten generell nicht effizient möglich ist.

An dieser Stelle habe ich die Ursache nicht weiter untersucht. Wenn ich ernsthaft ein neuronales Netzwerk trainieren will, ist sicher jeder Desktop PC auch mit aktuellen CPUs und Grafikkarte schnell überfordert und es bleibt nur das Ausweichen auf einen entsprechenden Cloud Anbieter. Aber das ist dann zu viel für heute Nacht :-)

Zählpixel

4 Kommentare to “TensorFlow 2 mit GPU Unterstützung”

  1. Matthias sagt:

    Dein Text ist widersprüchlich.

    Du schreibst einerseits von Alleinstellungsmerkmalen und großen Hoffnungen. Auf der anderen Seite von fehlender Dokumentation. Wenn deine Hardware nicht passend wäre, hätte die Software das als Warnung ausgegeben können.
    So alt ist die GeForce GTX 960 nun auch noch nicht.

    So richtig lädt mich dein Text nicht zum nachmachen ein.

  2. Sebastian sagt:

    Naja, die erste wichtige Erkenntnis ist: TensorFlow und CUDA sind schon wieder so komplex, dass man es nicht innerhalb weniger Stunden aufgesetzt bekommt. Und selbst wenn (siehe zweite Variante nur mittels Anaconda), weiß man immer noch nicht, warum es nicht viel bringt, ohne tiefer in die Materie einzusteigen.

    Und bitte nicht vergessen: Ich dokumentiere das hier primär, damit ich später die Kommandos nochmal nachschauen kann :-)

  3. Matthias sagt:

    Das ist auf alle Fälle ein relevanter Grund für Dokumentation.
    Ich habe mir TensorFlow und CUDA noch nicht angesehen. Nach deinen Worten sieht es für mich so aus als ob es dort nicht so gut mit der Dokumentation läuft.

  4. Michael sagt:

    @Installation CUDA/Tensorflow: ich habe es nach gut 15 Jahren absoluter Programmierabstinenz an einem Wochenende geschafft, das MNIST-Beispiel auf meiner GPU zum Laufen zu bringen. Ist nicht ganz trivial, aber eigentlich muss man nur sauber die Anleitungen befolgen…
    @Laufzeit: Bei der Konfiguration mit einem Hidden Layer von nur 128 Neuronen, kann ich mir gut vorstellen, dass die CPU schneller ist. Meine Tests haben ergeben, dass bei großen Netzten mit mehreren Hidden Layer zu mehreren hundert/tausend Neuronen die GPU (RTX 1050Ti) um einen Faktor von ca. 10 schneller als die CPU (Intel i5) ist. Erst bei wirklich großen Matrix Multiplikationen wird der Vorteil der GPU schlagend. Das dann aber deutlich. Mittlerweile habe ich eine neue CPU (AMD 5950X) und immer noch die alte Grafikkarte (RTX 1050Ti). Bei wirklich großen Netzen ist die alte GPU aber noch immer deutlich schneller als die neue CPU. Jetzt muss ich nur noch warten, bis es die neuen Grafikkarten zu vernünftigen Preisen gibt …

Schreiben sie ein Kommentar