Techblog

GPU-Unterstützung für CoreOS-Instanzen

Von Sebastian Wöhrl @swoehrl auf Twitter
11. September 2019

Machine Learning wird für Analytics in BigData-Systemen immer wichtiger. Eine Voraussetzung, um Machine Learning effizient einzusetzen: Wir müssen Modelle schnell trainieren können. Der beste Weg dahin ist die Verwendung von GPUs zur Beschleunigung des Trainings.

Da wir D2iQ DC/OS in unseren Projekten einsetzen, brauchten wir eine Möglichkeit, GPUs in unsere Cluster zu integrieren. Hardware-seitig ist das ein Kinderspiel, da alle großen Cloud-Anbieter wie Amazon AWS oder Microsoft Azure einen speziellen Maschinentypen mit integrierten GPUs anbieten. Die Herausforderung liegt bei der Software.

Als Basis für unsere Clusterknoten verwenden wir CoreOS Container Linux als minimalistisches, damit effizientes und für Container optimiertes Betriebssystem. Aufgrund seiner Schlankheit wird die Angriffsfläche reduziert und die Verwaltung der Knoten ist einfach. Nvidia, der GPU-Anbieter der Wahl für alle großen Cloud-Anbieter, unterstützt CoreOS jedoch offiziell nicht. Daher mussten wir einen benutzerdefinierten Weg finden, um Nvidia-Treiber unter CoreOS zu installieren und auszuführen.

Mit diesem Blogbeitrag beschreibe ich die von uns entwickelte Lösung (siehe auch bei Github).

Kernelmodule kompilieren

Der erste Schritt ist die Kompilierung der Nvidia-Kernelmodule für die genaue Kernelversion der von uns verwendeten CoreOS-Version. Um dies unabhängig von einer CoreOS-Instanz in unserem Cluster zu tun, starten wir einen Docker-Container mit einem Image, das das CoreOS-Entwickler-Image (von hier) mit Kernelquellen und zusätzlichen Tools enthält. Im Container laden wir die Kernelquellen herunter, bereiten sie für die Modulkompilierung vor (wie hier dokumentiert) und laden den regulären Nvidia-Installer von der Nvidia Website herunter.

Anstatt den Installer regulär auszuführen, lassen wir ihn nur seine Dateien extrahieren und führen dann manuell den Teil aus, der die Kernel-Module kompiliert. Dabei verweisen wir auf unsere vorbereiteten CoreOS-Kernel-Quellen anstatt auf den normalerweise genutzten aktuell laufenden Kernel. Über Kommandozeilenargumente unterbinden wir auch die Installation der frisch erstellen Module.

  1. ./NVIDIA-Linux-x86_64-${NVIDIA_DRIVER_VERSION}.run -x
  2. cd NVIDIA-Linux-x86_64-${NVIDIA_DRIVER_VERSION}
  3. IGNORE_MISSING_MODULE_SYMVERS=1 ./nvidia-installer -s -n --kernel-source-path=/usr/src/linux --no-check-for-alternate-installs --kernel-install-path=$WORKDIR --skip-depmod || echo "install failure is ok"

DC/OS-Setup-Prozess erweitern

Wir wollen dann diese Module und alle unterstützenden Bibliotheken und Binärdateien auf unseren CoreOS-Instanzen im Cluster installieren. Um den Prozess so einfach wie möglich zu gestalten, verzichten wir auf die Erstellung eigener CoreOS-Images und erweitern stattdessen einfach unseren bestehenden DC/OS-Setup-Prozess. Dazu komprimieren wir zunächst die Nvidia-Kernelmodule, Bibliotheken und Binärdateien in eine einzige Archivdatei und laden sie an einen Ort hoch, der für alle Clusterknoten erreichbar ist.

Unser Einrichtungsprozess ist über Terraform automatisiert, so dass wir im Cluster problemlos Knoten hinzufügen, aktualisieren und entfernen können. Mit Terraform erstellen wir neue VM-Instanzen über die Cloud-Provider-APIs, stellen sie mit unserer Basiskonfiguration bereit und installieren dann DC/OS. Unsere Werkzeuge basieren auf dem offiziellen DC/OS Terraform-Installer von D2iQ. Wir erweitern ihn einfach, um die Archivdatei herunterzuladen, ihren Inhalt zu extrahieren und die Kernelmodule zu laden. Dies reicht bereits aus, um die GPU-Instanzen für DC/OS verfügbar zu machen.

Da dieser Prozess nicht offiziell unterstützt wird, funktioniert die normale GPU-Integration in DC/OS nicht vollständig. GPUs werden erkannt und können in Marathon-Apps und Metronom-Jobs verwendet werden (ab DC/OS 1.13, für 1.12 benötigt ihr einen Patch für Metronom, damit es funktioniert). Was nicht funktioniert ist das kleine Helfer-Programm, das alle Nvidia-Bibliotheken und -Binärdateien sammelt und für GPU-Container zur Verfügung stellt.

Mit Nvidia zusammenbringen

Der Workaround besteht darin, das Verzeichnis, in dem die Treiber installiert sind, als Volume in die Container einzubinden. Dann kann man den Grafikprozessor normal verwenden, z.B. um das Modelltraining mit PyTorch zu beschleunigen.

Der Prozess, wie wir ihn beschrieben haben, ist zwischen den Neustarts der Knoten nicht persistent. Damit CoreOS die Nvidia-Kernelmodule beim Start lädt, haben wir eine einfache systemd unit erstellt, die vor DC/OS startet und die Kernelmodule lädt. Diese Unit muss vor dem Start von DC/OS laufen, da DC/OS sonst die GPUs nicht erkennen kann.

Wir haben alle diese Schritte in ein paar einfache Skripte gepackt und auf GitHub unter Open-Source-Lizenz zur Verfügung gestellt. Ihr könnt sie im Projekt gern verwenden, um GPU-Unterstützung für eure eigenen CoreOS-basierten DC/OS-Cluster hinzuzufügen.

Mit diesem automatisierten Prozess können wir unserem Cluster ganz einfach GPU-fähige Instanzen on-the-fly hinzufügen (da unsere Cluster auf AWS laufen, verwenden wir Instanzen vom Maschinen-Typ p3​) und dann unser PyTorch-basiertes Modelltraining durchführen. Dazu verwenden wir Metronome-Jobs. Eine vereinfachte Task-Definition sieht so aus:

  1. {
  2.   "id": "model-training",
  3.   "run": {
  4.     "cpus": 1,
  5.     "mem": 32768,
  6.     "disk": 0,
  7.     "gpus": 1,
  8.     "cmd": "python train.py",
  9.     "env": {
  10.       "LD_LIBRARY_PATH": "/mnt/mesos/sandbox/nvidia/lib"
  11.     },
  12.     "ucr": {
  13.       "image": {
  14.         "id": "docker.analytics.corp/model-training",
  15.         "kind": "docker"
  16.       }
  17.     },
  18.     "volumes": [
  19.       {
  20.         "containerPath": "nvidia",
  21.         "hostPath": "/opt/nvidia/",
  22.         "mode": "RO"
  23.       }
  24.     ],
  25.     "restart": {
  26.       "policy": "NEVER"
  27.     }
  28.   },
  29.   "schedules": []
  30. }

 

Wichtig zu beachten ist, dass wir den Nvidia-Ordner als Volume hinzugefügt und die Umgebungsvariable LD_LIBRARY_PATH so gesetzt haben, dass PyTorch die Nvidia-Bibliotheken aufnimmt.

 

Und schließlich unser Haftungsausschluss: Die Informationen in diesem Blogbeitrag und im github-Repository werden zur Verfügung gestellt, so wie sie sind. Das Verfahren wird von D2iQ oder Nvidia nicht offiziell unterstützt. Die Nutzung erfolgt auf eure eigene Gefahr.

Neuen Kommentar schreiben

Public Comment form

  • Zulässige HTML-Tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd><p><h1><h2><h3>

Plain text

  • Keine HTML-Tags erlaubt.
  • Internet- und E-Mail-Adressen werden automatisch umgewandelt.
  • HTML - Zeilenumbrüche und Absätze werden automatisch erzeugt.

ME Landing Page Question