GPU-Survival-Toolkit für das AI-Zeitalter
(journal.hexmos.com)- Für die AI-Entwicklung reicht die sequentielle Ausführung im CPU-Stil nicht mehr aus; um Trainings- und Inferenzleistung richtig zu beherrschen, muss man das Modell massiver Parallelverarbeitung auf GPUs verstehen
- CPUs haben im Consumer-Bereich meist 2–16 Kerne und sind stark bei Single-Thread- und bedingungsabhängigen Verzweigungsaufgaben, während GPUs mit Tausenden kleiner Kerne für Matrixoperationen, Bildverarbeitung und Deep Learning im Vorteil sind
- AWS bietet GPU-Laufzeitumgebungen wie P3/P4, P5/Inf1, G4 und Amazon SageMaker an; p3.2xlarge kostet $3.06 pro Stunde, p5.48xlarge $98.32 und g4dn.xlarge etwa $0.526
- Mit NVIDIA CUDA können Entwickler den gesamten Ablauf paralleler Ausführung direkt steuern – von GPU-Speicherallokation über Datenkopien und Kernel-Ausführung bis zur Kompilierung
- Beispiele für Array-Addition, Mandelbrot-Erzeugung und ein CNN zur Katzen-Hunde-Klassifikation zeigen, wie sequentielle Schleifen auf GPU-Threads aufgeteilt werden; beim Mandelbrot sinkt die Laufzeit von 4.07 Sekunden auf der CPU auf 0.0046 Sekunden auf der GPU
Warum CPU-Wissen allein nicht ausreicht
- Viele Entwickler haben Lernen und Problemlösung in einer CPU-zentrierten Denkweise verinnerlicht, doch CPUs arbeiten grundsätzlich auf Basis einer sequentiellen Architektur
- Traditionelle CPUs führen Befehle linear aus und optimieren wenige leistungsstarke Kerne auf Single-Thread-Performance
- Wenn viele Aufgaben gleichzeitig verarbeitet werden müssen, steigen durch die sequentielle Ausführung die Kosten dafür, jede Aufgabe nacheinander abzuarbeiten
- Mit Multithreading lässt sich die Leistung steigern, doch die grundlegende Designphilosophie von CPUs bleibt weiterhin stark an sequentieller Ausführung orientiert
AI-Modelle und Parallelverarbeitung
- Moderne AI-Architekturen wie Transformer steigern ihre Trainingsleistung durch Parallelverarbeitung
- RNNs arbeiten sequentiell, aber Transformer wie GPT können mehrere Wörter gleichzeitig verarbeiten, was Trainingseffizienz und Modellfähigkeit erhöht
- Paralleles Training macht größere Modelle möglich, und größere Modelle schaffen die Grundlage für bessere Ausgaben
- Parallelität gilt nicht nur für die Sprachverarbeitung, sondern auch für die Bilderkennung
- AlexNet ist ein Beispiel dafür, mehrere Teile eines Bildes gleichzeitig zu verarbeiten, um Muster zu erkennen
- Wegen ihres auf Single-Thread-Leistung ausgerichteten Designs können CPUs die großen Mengen paralleler Berechnungen, die komplexe AI-Modelle benötigen, nur schwer effizient verteilen und ausführen
Wie GPUs Engpässe reduzieren
- GPUs sind nicht mit wenigen großen, leistungsstarken CPU-Kernen aufgebaut, sondern mit vielen kleinen, spezialisierten Kernen
- Die Parallelität von GPUs zeigt sich besonders bei Workloads, die dieselbe Art von Operation massenhaft wiederholen, etwa Grafik-Rendering oder komplexe mathematische Berechnungen
- Deep-Learning-Frameworks wie TensorFlow sind darauf optimiert, GPU-Leistung zur Beschleunigung von Modelltraining und Inferenz zu nutzen
- Das Training neuronaler Netze umfasst viele Matrixoperationen, und GPUs sind durch ihre große Anzahl an Kernen stark darin, solche Operationen zu parallelisieren
Unterschiede in den Rollen von CPU und GPU
-
CPU
- CPUs sind auf sequentielle Verarbeitung ausgelegt und stark bei Aufgaben, die einen einzelnen Befehlsfluss linear ausführen
- Sie eignen sich für General-Purpose-Computing, Systemaufgaben und die Verarbeitung komplexer Algorithmen mit bedingten Verzweigungen
- Consumer-CPUs haben gewöhnlich vergleichsweise wenige Kerne, meist im Bereich von 2–16 Kernen
- Jeder Kern kann seinen eigenen Befehlssatz unabhängig verarbeiten
-
GPU
- GPUs sind als parallele Architektur konzipiert und effizient darin, viele Teilaufgaben gleichzeitig zu verarbeiten
- Sie eignen sich für Grafik-Rendering, komplexe mathematische Berechnungen und die Ausführung parallelisierbarer Algorithmen
- Aufgaben werden in kleinere parallele Einheiten zerlegt, sodass viele Operationen gleichzeitig ausgeführt werden können
- GPU-Kerne gehen oft in die Tausende und sind in streaming multiprocessors (SMs) oder ähnlichen Strukturen organisiert
- Sie eignen sich für Aufgaben, die viele Daten gleichzeitig verarbeiten, etwa Bild- und Videoverarbeitung, Deep Learning und wissenschaftliche Simulationen
GPU-Umgebungen zur Auswahl in AWS
- AWS bietet verschiedene GPU-Instanzen für Aufgaben wie Machine Learning an
-
Allzweck-GPU-Instanzen
-
Für Inferenz optimierte Instanzen
- Inferenz ist der Prozess, bei dem ein trainiertes AI-Modell mit Echtzeitdaten gefüttert wird, um Vorhersagen zu treffen oder Aufgaben zu lösen
- P5 und Inf1 sind auf Machine-Learning-Inferenz ausgelegt, bei der niedrige Latenz und Kosteneffizienz wichtig sind
- p5.48xlarge kostet $98.32 pro Stunde und bietet 8 NVIDIA H100 GPUs mit jeweils 80 GB Speicher, insgesamt also 640 GB Videospeicher
-
Grafikoptimierte Instanzen
- G4 instances wurden für grafikintensive Aufgaben entwickelt
- Spieleentwickler können G4-Instanzen verwenden, um 3D-Grafiken für Games zu rendern
- g4dn.xlarge kostet $0.526 pro Stunde und nutzt 1 NVIDIA T4 GPU mit 16 GB Speicher
-
Verwalteter Machine-Learning-Service
- Amazon SageMaker ist ein verwalteter Service für Machine Learning und bietet Zugriff auf GPU-basierte Instanzen wie P3, P4 und P5
- SageMaker eignet sich für Organisationen, die mit Machine Learning starten möchten, ohne die zugrunde liegende Infrastruktur selbst zu verwalten
- Es gibt eine separate Dokumentation zu Amazon SageMaker-Preisen
Grundlegende Nutzung von NVIDIA CUDA
- CUDA ist eine von NVIDIA entwickelte Plattform für paralleles Computing sowie ein Programmiermodell, mit dem Anwendungen mithilfe von GPU-Beschleunigern schneller ausgeführt werden können
- Die Beispiele zeigen den CUDA-Entwicklungsablauf von GPU-Speicherallokation über Datenkopie und Kernel-Ausführung bis zur Rückgabe der Ergebnisse
-
Installationsablauf
- Von CUDA den base installer und den driver installer herunterladen
- In der
.bashrcim Home-Verzeichnis die folgenden Umgebungsvariablen ergänzenexport PATH="/usr/local/cuda-12.3/bin:$PATH"export LD_LIBRARY_PATH="/usr/local/cuda-12.3/lib64:$LD_LIBRARY_PATH"
- Die folgenden Befehle ausführen
sudo apt-get install cuda-toolkitsudo apt-get install nvidia-gds
- Das System neu starten, damit die Änderungen wirksam werden
-
Nützliche Prüfkommandos
lspci | grep VGA: identifiziert und listet die GPUs im System aufnvidia-smi: liefert Detailinformationen wie Auslastung, Temperatur und Speichernutzung der NVIDIA-GPUsudo lshw -C display: zeigt Informationen zu Display-Controllern wie Grafikkarten aninxi -G: zeigt Informationen zum Grafik-Subsystem einschließlich GPU und Displaysudo hwinfo --gfxcard: dient zum Prüfen detaillierter Informationen über die Grafikkarte des Systems
Array-Addition mit CUDA parallelisieren
- Die Addition von Arrays ist ein gut geeignetes Problem, um GPU-Parallelisierung zu erklären
- Die Beispiel-Arrays sind
A = [1,2,3,4,5,6]undB = [7,8,9,10,11,12], das Ergebnis istC = [8,10,12,14,16,18] - Beim CPU-Ansatz werden die Array-Elemente nacheinander durchlaufen und addiert
- Bei größeren Datenmengen steigt die Laufzeit des sequentiellen Ansatzes, während die GPU Operationen wie
1+7,2+8,3+9gleichzeitig ausführen kann - Das CUDA-Beispiel verwendet eine
.cu-Kernel-Datei__global__kennzeichnet eine Kernel-Funktion, die auf der GPU aufgerufen wirdvectorAddnimmt drei Integer-Pointera,bundcentgegen und führt die Vektoraddition austhreadIdx.xliefert den Index des aktuellen Threads- Jeder Thread speichert die Summe des entsprechenden Elements in
c[i]
- Die
main-Funktion läuft in der Reihenfolge GPU-Speicherallokation, Datenkopie, Kernel-Ausführung und Ergebniskopie ab- Mit
cudaMallocwird Speicher fürcudaA,cudaBundcudaCauf der GPU reserviert - Mit
cudaMemcpywerdenaundbvom Host auf die GPU kopiert - Mit
vectorAdd <<<1, sizeof(a) / sizeof(a[0])>>>wird der Kernel ausgeführt - Der Ergebnisvektor
cudaCwird von der GPU zurück auf den Host kopiert
- Mit
- Zum Kompilieren und Ausführen wird der Befehl
nvccverwendet - Der vollständige Code ist verfügbar
GPU-Nutzung für die Bilderzeugung in Python
- Die Erzeugung der Mandelbrot-Menge erstellt komplexe visuelle Muster aus dem Verhalten von Zahlen in einer bestimmten Gleichung und ist ressourcenintensiv
- Das CPU-basierte Python-Beispiel durchläuft jedes Pixel und berechnet den Mandelbrot-Wert; für ein 1024×1536-Bild werden 4.07 Sekunden benötigt
- Die GPU-beschleunigte Version verwendet die Numba library
- Der Decorator
@jitführt eine Just-In-Time-Kompilierung aus, die Python-Code in Maschinencode umwandelt - Mit
cuda.jitwirdmandel_gpuerstellt und mitdevice=Trueso markiert, dass es auf der GPU ausgeführt wird mandel_kernelläuft auf der CUDA-GPU und verteilt die Aufgabe der Mandelbrot-Erzeugung auf GPU-Threads
- Der Decorator
create_fractal_gpuübernimmt GPU-Speicherallokation, Thread- und Block-Konfiguration, Ausführung des GPU-Kernels, Synchronisierung und Ergebniskopie- Es wird
threadsperblock = (16, 16)verwendet - Mit
cuda.synchronize()wird auf den Abschluss der GPU-Arbeit gewartet - Mit
d_image.copy_to_host(image)wird das Ergebnis auf die CPU-Seite zurückkopiert
- Es wird
- Die GPU-Ausführungszeit liegt bei 0.0046 Sekunden und ist damit deutlich schneller als der CPU-basierte Code
- Der vollständige Code ist verfügbar
Training eines neuronalen Netzes zur Katzen-Hunde-Klassifikation mit GPU
- Um zu zeigen, wie GPUs in AI eingesetzt werden, wird ein Beispiel für ein neuronales Netz zur Unterscheidung von Katzen und Hunden verwendet
- Voraussetzungen sind CUDA und TensorFlow
- TensorFlow lässt sich mit
pip install tensorflow[and-cuda]installieren - Als Datensatz wird Kaggle Dogs vs. Cats verwendet
- Nach dem Download werden Katzen- und Hundebilder in getrennten Unterordnern des Trainingsverzeichnisses organisiert
- TensorFlow lässt sich mit
- Das Modell verwendet ein Convolutional Neural Network (CNN)
- pandas und numpy werden für die Datenmanipulation verwendet
Sequentialdient dazu, die Schichten des neuronalen Netzes linear zu stapelnConvolution2D,MaxPooling2D,DenseundFlattensind die verwendeten CNN-SchichtenImageDataGeneratorwird für Data Augmentation in Echtzeit während des Trainings eingesetzt
- Die Trainingsdaten werden mit
ImageDataGeneratorgeladen- Auf die Trainingsdaten werden
rescale=1./255,shear_range=0.2,zoom_range=0.2undhorizontal_flip=Trueangewendet - Die Eingabebilder werden auf Größe
(64, 64)gesetzt, mit Batch-Größe 32 und im Modus für binäre Klassifikation verarbeitet
- Auf die Trainingsdaten werden
- Die CNN-Struktur besteht aus Convolution, Max Pooling, Flatten, Dense-Layern und einer sigmoid-Ausgabe
- Das Modell wird mit dem Optimizer
adam, der Verlustfunktionbinary_crossentropyund der Metrikaccuracykompiliert - Das Training läuft mit
epochs=25undvalidation_steps=2000, gespeichert wird mitclassifier.save('trained_model.h5')in einer.h5-Datei - Der Inferenz-Code lädt
trained_model.h5, skaliert Bilder auf(64, 64)und gibt bei einem Vorhersagewert von mindestens 0.5dog, sonstcataus - Der vollständige Code ist verfügbar
Reichweite des GPU-Einsatzes
- Im AI-Zeitalter lässt sich die Bedeutung von GPUs kaum ignorieren, und Entwickler sollten ihre Fähigkeiten besser verstehen
- Beim Übergang von sequentiellen Algorithmen zu parallelisierten Algorithmen werden GPUs zu einem Werkzeug zur Beschleunigung komplexer Berechnungen
- Die Parallelverarbeitungsfähigkeit von GPUs ist besonders vorteilhaft für große Datensätze und komplexe neuronale Netzarchitekturen in AI- und Machine-Learning-Aufgaben
- GPUs werden über klassische Machine-Learning-Bereiche hinaus auch in wissenschaftlicher Forschung, Simulationen und datenintensiven Aufgaben eingesetzt
- Ihre Parallelverarbeitung hilft bei der Lösung von Problemen in ganz unterschiedlichen Feldern wie Wirkstoffforschung, Klimamodellierung und Finanzsimulationen
1 Kommentare
Hacker-News-Kommentare
Der Code in diesem Artikel ist falsch. Der CUDA-Kernel wird überhaupt nicht aufgerufen: https://github.com/RijulTP/GPUToolkit/blob/f17fec12e008d0d37...
90 % der Zeit, die zum „Berechnen“ der Mandelbrot-Menge mit JIT-kompiliertem Code gemessen werden, gehen nicht in die eigentliche Berechnung, sondern in die Funktionskompilierung
Wenn man CUDA richtig lernen will, ist die Implementierung einer Matrixmultiplikation eine gute Übung, und als nützliche Tutorials eignen sich https://cnugteren.github.io/tutorial/pages/page1.html und https://siboehm.com/articles/22/CUDA-MMM
Sie nimmt 32-Bit-Gleitkomma-Vektoren X und Y sowie einen Skalar A, multipliziert jedes X[i] mit A und addiert das Ergebnis zu Y[i]: https://developer.nvidia.com/blog/six-ways-saxpy/
Es wird zwar behauptet, dass „jeder Entwickler das wissen sollte“, tatsächlich ist der Artikel aber eher ein Text darüber, wie GPUs in der KI eingesetzt werden. Die meisten Entwickler sind keine KI-Entwickler und interagieren weder direkt mit KI noch nutzen sie selbst direkt GPUs
Außerdem wird 3D-Grafik, der eigentliche Hauptgrund für die Existenz von GPUs, fast gar nicht behandelt
Mit Grundwissen versteht man auch besser die „AI“-Geschichten, die dem Management verkauft werden
Die Haltung „angrenzende Gebiete brauche ich nicht“ habe ich in der Schule oft gesehen. Im Bereich Systemadministration meinten Kommilitonen, sie müssten kein Programmieren können, brauchten dann aber doch Scripting; in der Softwareentwicklungsschule hieß es, Netzwerke müsse man nicht kennen, aber ein paar Jahre später tauchte DevOps in Stellenausschreibungen überall auf
Wenn der Artikel ungefähr 1500 Wörter hat, braucht man selbst bei aufmerksamem Lesen vielleicht 12 Minuten, und auch 2 Stunden für das Ausprobieren der Codebeispiele sind keine große Investition. Natürlich nur unter der Voraussetzung, dass der Artikel überhaupt eine gute Einführung ist
curlverschickt. Ich bin immer noch Embedded-Entwickler, habe seitdem aber viel über Backend, Frontend und Infrastruktur gelernt, und es wirkt gut möglich, dass sich in den nächsten Jahren branchenweit mit AI eine ähnliche Situation ergibtIch denke, Python in der KI so dominant ist, weil die Beziehung zwischen Python und C der Beziehung zwischen CPU und GPU ähnelt
GPUs bieten sehr hohe Performance, sind aber schwer direkt zu programmieren, deshalb arbeiten die Leute mit GPUs über High-Level-API-Aufrufe wie in PyTorch
C bietet ebenfalls hohe Performance, ist aber schwer zu programmieren, daher wird Python als Abstraktionsschicht über C verwendet
Es ist nicht klar, ob die Leute GPUs so tiefgehend verstehen müssen. Das gilt umso mehr, wenn man nicht tief in KI-Training oder -Betrieb einsteigt, und wenn Moores Gesetz endet und Multithreading zum wichtigsten Weg für Geschwindigkeitssteigerungen wird, ist es gut möglich, dass neue Sprachen entstehen, die auf Paradigmen der parallelen Programmierung zugeschnitten sind. Mojo wirkt wie ein möglicher Anfang davon
Also so, dass von einfachen Schleifenberechnungen bis hin zu allem anderen jede Anweisung im Hintergrund intelligent alle CPU-Kerne parallel nutzt und geeignete Aufgaben an die GPU weiterreicht
Ich frage mich, ob es solche Versuche schon gab und ob das überhaupt möglich ist
Die Erklärung „Wenn eine CPU auf mehrere Aufgaben trifft, teilt sie ihre Ressourcen so auf, dass sie jede Aufgabe einzeln bearbeitet“ ist zu stark vereinfacht. Man wünscht sich fast, CPUs wären noch so simpel
Dass sich der Artikel auf das Programmiermodell konzentriert, ist nachvollziehbar, aber aus Performance-Sicht ist die Aussage „CPUs führen Befehle sequentiell aus“ grundsätzlich falsch. Pipelines führen Befehle parallel aus, es gibt SIMD, und mehrere Kerne können gemeinsam an demselben Problem arbeiten
Der große Unterschied ist, dass CPUs viel Silizium und Energie für die Verarbeitung von Kontrollfluss aufwenden, um einen einzelnen Thread effizient auszuführen, während GPUs diese Ressourcen in mehr Recheneinheiten stecken und sehr viele Threads ausführen, um Kontrollfluss- und Speicherlatenzen zu verbergen
Die Aussage, dass CPUs gut für seriellen Code und GPUs gut für parallelen Code sind, ist bis zu einem gewissen Grad richtig, aber eine ziemlich grobe Näherung. Nimmt man ein ähnliches Leistungsbudget von einigen hundert Watt an, hat eine CPU etwa 100 „Kerne“, die unabhängige Aufgaben einzeln ausführen, einschließlich Hyperthreads, und versteckt Speicherlatenz durch Branch Prediction und Pipelining
Eine GPU hat etwa 100 „Compute Units“, und jede Einheit führt ungefähr 80 unabhängige Aufgaben im Wechsel aus und versteckt Speicherlatenz, indem sie die nächste Instruktion einer anderen Aufgabe ausführt
Die Terminologie ist ziemlich verwirrend, und während eine CPU wahrscheinlich 256-Bit-breite Vektoreinheiten und eine GPU wahrscheinlich 2048-Bit-breite Vektoreinheiten hat, wirken beide Architekturen aus etwas Abstand betrachtet ziemlich ähnlich
Man könnte das Xeon Chi nennen
Da die meisten Programmiersprachen wie CPUs auf sequenzielle Verarbeitung ausgelegt sind, während Erlang/Elixir eher wie GPUs auf Parallelität ausgelegt sind, frage ich mich, ob Nx / Axon an Bedeutung gewinnen wird: https://github.com/elixir-nx/
Ich brauche einen Einkaufsratgeber. Ich würde gerne wissen, wie viel man mindestens ausgeben muss und was in den jeweiligen Budgetklassen die beste Wahl ist. Das Problem ist, dass sich diese Informationen gelegentlich ändern, und ich weiß nicht, ob es dafür eine laufend aktuell gehaltene Quelle gibt
https://colab.google/
https://www.kaggle.com/docs/notebooks
https://www.paperspace.com/gradient/free-gpu
Sind wir wieder bei einer Art Clickbait im Stil von „was alle Entwickler wissen sollten“ angekommen?
Ich mag es, Komplexität frontal anzugehen, und kenne sowohl quantitative Methoden als auch qualitative Details in Bereichen wie Computerhardware zumindest einigermaßen, daher freue ich mich über Artikel, die die Details eines Fachgebiets wirklich gut vermitteln
Ob „What every programmer should know about memory“ nun wirklich etwas ist, das alle Programmierer wissen müssen, ist eine andere Frage, aber ein guter Programmierer sollte zumindest ein Gefühl dafür haben, wie Computer tatsächlich funktionieren. Die zentrale Erkenntnis aus diesem Artikel, Lokalität, ergibt sich oft ganz natürlich aus gutem Code, der schnell, leicht nachvollziehbar und für das Problem passend ist
Guter Artikel, aber AWS-P5-Instanzen sind zusammen mit P4d und P4de klar eher auf Training als auf Inferenz ausgerichtet. Für Inferenz besser geeignete Instanztypen sind G4dn und G5, die jeweils T4- und A10G-GPUs verwenden
GPU-Programmierung ist für mich noch fast völlig neu, aber ich habe den Artikel mit Interesse gelesen. Es ist erstaunlich, wie weit sich das entwickelt hat, dass man ein einfaches „Hund oder Katze“-Neuronales-Netz so leicht trainieren kann