Was ist CUDA? Parallele Programmierung für GPUs

CUDA ist eine parallele Computerplattform und ein Programmiermodell, die von Nvidia für das allgemeine Rechnen auf eigenen GPUs (Grafikprozessoren) entwickelt wurden. Mit CUDA können Entwickler rechenintensive Anwendungen beschleunigen, indem sie die Leistung von GPUs für den parallelisierbaren Teil der Berechnung nutzen.

Während andere APIs für GPUs wie OpenCL vorgeschlagen wurden und es wettbewerbsfähige GPUs von anderen Unternehmen wie AMD gibt, dominiert die Kombination von CUDA- und Nvidia-GPUs mehrere Anwendungsbereiche, einschließlich Deep Learning, und ist eine Grundlage für einige von ihnen die schnellsten Computer der Welt.

Grafikkarten sind wohl so alt wie der PC - wenn Sie den IBM Monochrome Display Adapter von 1981 als Grafikkarte betrachten. Bis 1988 konnte man von ATI (dem Unternehmen, das schließlich von AMD übernommen wurde) eine 16-Bit-2D-VGA-Wonder-Karte erhalten. Bis 1996 konnten Sie einen 3D-Grafikbeschleuniger von 3dfx Interactive kaufen, um den Ego-Shooter Quake mit voller Geschwindigkeit laufen zu lassen.

Ebenfalls 1996 versuchte Nvidia, auf dem Markt für 3D-Beschleuniger mit schwachen Produkten zu konkurrieren, lernte jedoch im Laufe der Zeit und führte 1999 die erfolgreiche GeForce 256 ein, die erste Grafikkarte, die als GPU bezeichnet wurde. Zu dieser Zeit war der Hauptgrund für eine GPU das Spielen. Erst später verwendeten die Leute GPUs für Mathematik, Naturwissenschaften und Ingenieurwissenschaften.

Der Ursprung von CUDA

2003 stellte ein Forscherteam unter der Leitung von Ian Buck Brook vor, das erste weit verbreitete Programmiermodell, das C um datenparallele Konstrukte erweitert. Buck kam später zu Nvidia und leitete 2006 die Einführung von CUDA, der ersten kommerziellen Lösung für Allzweck-Computing auf GPUs.

OpenCL vs. CUDA

Der CUDA-Konkurrent OpenCL wurde 2009 von Apple und der Khronos Group ins Leben gerufen, um einen Standard für heterogenes Computing bereitzustellen, der nicht auf Intel / AMD-CPUs mit Nvidia-GPUs beschränkt war. Obwohl OpenCL aufgrund seiner Allgemeinheit attraktiv klingt, hat es auf Nvidia-GPUs nicht so gute Leistungen wie CUDA erbracht, und viele Deep-Learning-Frameworks unterstützen es entweder nicht oder nur nachträglich, sobald die CUDA-Unterstützung veröffentlicht wurde.

CUDA-Leistungssteigerung

CUDA hat seinen Anwendungsbereich im Laufe der Jahre verbessert und erweitert, mehr oder weniger im Gleichschritt mit verbesserten Nvidia-GPUs. Ab CUDA Version 9.2 können Sie mit mehreren P100-Server-GPUs bis zu 50-fache Leistungsverbesserungen gegenüber CPUs erzielen. Der V100 (in dieser Abbildung nicht dargestellt) ist für einige Lasten noch dreimal schneller. Die vorherige Generation von Server-GPUs, der K80, bot 5- bis 12-fache Leistungsverbesserungen gegenüber CPUs.

Nvidia

Der Geschwindigkeitsschub durch GPUs ist für Hochleistungsrechner gerade rechtzeitig gekommen. Die Single-Threaded-Leistungssteigerung von CPUs im Laufe der Zeit, die laut Moores Gesetz alle 18 Monate verdoppelt werden soll, hat sich auf 10 Prozent pro Jahr verlangsamt, da die Chiphersteller während des Herstellungsprozesses auf physikalische Grenzen stießen, einschließlich Größenbeschränkungen für die Auflösung der Chipmasken und die Chipausbeute und Wärmegrenzen für Taktfrequenzen zur Laufzeit.

Nvidia

CUDA-Anwendungsdomänen

Nvidia

CUDA- und Nvidia-GPUs wurden in vielen Bereichen eingesetzt, die eine hohe Gleitkomma-Rechenleistung erfordern, wie im obigen Bild bildlich zusammengefasst. Eine umfassendere Liste enthält:

  1. Computerfinanzierung
  2. Klima-, Wetter- und Ozeanmodellierung
  3. Datenwissenschaft und Analytik
  4. Deep Learning und maschinelles Lernen
  5. Verteidigung und Geheimdienst
  6. Fertigung / AEC (Architektur, Ingenieurwesen und Konstruktion): CAD und CAE (einschließlich rechnergestützter Fluiddynamik, rechnergestützter Strukturmechanik, Entwurf und Visualisierung sowie Automatisierung des elektronischen Entwurfs)
  7. Medien und Unterhaltung (einschließlich Animation, Modellierung und Rendering; Farbkorrektur und Maserung; Compositing; Finishing und Effekte; Bearbeitung; Codierung und digitale Verbreitung; On-Air-Grafiken; On-Set-, Review- und Stereo-Tools sowie Wettergrafiken)
  8. Medizinische Bildgebung
  9. Öl und Gas
  10. Forschung: Hochschulbildung und Supercomputing (einschließlich Computerchemie und -biologie, numerische Analytik, Physik und wissenschaftliche Visualisierung)
  11. Sicherheit und Schutz
  12. Tools und Management

CUDA im tiefen Lernen

Deep Learning hat einen übergroßen Bedarf an Rechengeschwindigkeit. Um beispielsweise die Modelle für Google Translate im Jahr 2016 zu trainieren, haben die Teams von Google Brain und Google Translate Hunderte von einwöchigen TensorFlow-Läufen mit GPUs durchgeführt. Zu diesem Zweck hatten sie 2.000 Server-GPUs von Nvidia gekauft. Ohne GPUs hätte die Konvergenz dieser Trainingsläufe eher Monate als eine Woche gedauert. Für die Produktionsbereitstellung dieser TensorFlow-Übersetzungsmodelle verwendete Google einen neuen benutzerdefinierten Verarbeitungschip, die TPU (Tensor Processing Unit).

Neben TensorFlow verlassen sich viele andere DL-Frameworks für die GPU-Unterstützung auf CUDA, darunter Caffe2, CNTK, Databricks, H2O.ai, Keras, MXNet, PyTorch, Theano und Torch. In den meisten Fällen verwenden sie die cuDNN-Bibliothek für die Berechnungen des tiefen neuronalen Netzwerks. Diese Bibliothek ist für das Training der Deep-Learning-Frameworks so wichtig, dass alle Frameworks, die eine bestimmte Version von cuDNN verwenden, für äquivalente Anwendungsfälle im Wesentlichen die gleichen Leistungszahlen aufweisen. Wenn sich CUDA und cuDNN von Version zu Version verbessern, werden bei allen Deep-Learning-Frameworks, die auf die neue Version aktualisiert werden, Leistungssteigerungen erzielt. Die Leistung unterscheidet sich tendenziell von Framework zu Framework darin, wie gut sie auf mehrere GPUs und mehrere Knoten skaliert werden kann.

CUDA-Programmierung

Nvidia

CUDA Toolkit

Das CUDA Toolkit enthält Bibliotheken, Debugging- und Optimierungstools, einen Compiler, eine Dokumentation und eine Laufzeitbibliothek zum Bereitstellen Ihrer Anwendungen. Es verfügt über Komponenten, die Deep Learning, lineare Algebra, Signalverarbeitung und parallele Algorithmen unterstützen. Im Allgemeinen unterstützen CUDA-Bibliotheken alle Familien von Nvidia-GPUs, bieten jedoch die beste Leistung der neuesten Generation, wie z. B. der V100, die für Deep-Learning-Trainings-Workloads dreimal schneller sein kann als die P100. Die Verwendung einer oder mehrerer Bibliotheken ist der einfachste Weg, um GPUs zu nutzen, sofern die von Ihnen benötigten Algorithmen in der entsprechenden Bibliothek implementiert wurden.

Nvidia

CUDA Deep Learning Bibliotheken

Im Bereich Deep Learning gibt es drei wichtige GPU-beschleunigte Bibliotheken: cuDNN, die ich zuvor als GPU-Komponente für die meisten Open Source-Deep-Learning-Frameworks erwähnt habe; TensorRT, Nvidias leistungsstarker Deep-Learning-Inferenzoptimierer und zur Laufzeit; und DeepStream, eine Video-Inferenzbibliothek. Mit TensorRT können Sie neuronale Netzwerkmodelle optimieren, mit hoher Genauigkeit auf geringere Präzision kalibrieren und die trainierten Modelle in Clouds, Rechenzentren, eingebetteten Systemen oder Produktplattformen für die Automobilindustrie bereitstellen.

Nvidia

CUDA-Bibliotheken für lineare Algebra und Mathematik

Die lineare Algebra untermauert Tensorberechnungen und damit tiefes Lernen. BLAS (Basic Linear Algebra Subprograms), eine Sammlung von Matrixalgorithmen, die 1989 in Fortran implementiert wurden, wird seitdem von Wissenschaftlern und Ingenieuren verwendet. cuBLAS ist eine GPU-beschleunigte Version von BLAS und die leistungsstärkste Methode, um Matrixarithmetik mit GPUs durchzuführen. cuBLAS geht davon aus, dass die Matrizen dicht sind; cuSPARSE verarbeitet spärliche Matrizen.

Nvidia

CUDA-Signalverarbeitungsbibliotheken

Die schnelle Fourier-Transformation (FFT) ist einer der grundlegenden Algorithmen für die Signalverarbeitung. Es wandelt ein Signal (z. B. eine Audio-Wellenform) in ein Frequenzspektrum um. cuFFT ist eine GPU-beschleunigte FFT.

Codecs, die Standards wie H.264 verwenden, codieren / komprimieren und decodieren / dekomprimieren Videos für die Übertragung und Anzeige. Das Nvidia Video Codec SDK beschleunigt diesen Prozess mit GPUs.

Nvidia

CUDA-Bibliotheken für parallele Algorithmen

Die drei Bibliotheken für parallele Algorithmen haben alle unterschiedliche Zwecke. NCCL (Nvidia Collective Communications Library) dient zur Skalierung von Apps über mehrere GPUs und Knoten hinweg. nvGRAPH dient zur parallelen Graphanalyse. und Thrust ist eine C ++ - Vorlagenbibliothek für CUDA, die auf der C ++ - Standardvorlagenbibliothek basiert. Thrust bietet eine umfangreiche Sammlung datenparalleler Grundelemente wie Scannen, Sortieren und Reduzieren.

Nvidia

CUDA vs. CPU-Leistung

In einigen Fällen können Sie anstelle der entsprechenden CPU-Funktionen Drop-In-CUDA-Funktionen verwenden. Beispielsweise können die GEMM-Matrixmultiplikationsroutinen von BLAS durch GPU-Versionen ersetzt werden, indem einfach eine Verknüpfung mit der NVBLAS-Bibliothek hergestellt wird:

Nvidia

Grundlagen der CUDA-Programmierung

Wenn Sie keine CUDA-Bibliotheksroutinen finden, um Ihre Programme zu beschleunigen, müssen Sie sich in der CUDA-Programmierung auf niedriger Ebene versuchen. Das ist jetzt viel einfacher als damals, als ich es Ende der 2000er Jahre zum ersten Mal ausprobiert habe. Unter anderem gibt es eine einfachere Syntax und bessere Entwicklungswerkzeuge. Mein einziges Problem ist, dass unter MacOS der neueste CUDA-Compiler und der neueste C ++ - Compiler (von Xcode) selten synchron sind. Man muss ältere Befehlszeilentools von Apple herunterladen und zu ihnen wechseln xcode-select, um den CUDA-Code zum Kompilieren und Verknüpfen zu erhalten.

Betrachten Sie beispielsweise diese einfache C / C ++ - Routine, um zwei Arrays hinzuzufügen:

void add (int n, float * x, float * y)

{  

       für (int i = 0; i <n; i ++)      

             y [i] = x [i] + y [i];

}}

Sie können daraus einen Kernel machen, der auf der GPU ausgeführt wird, indem Sie __global__der Deklaration das Schlüsselwort hinzufügen , und den Kernel mithilfe der dreifachen Klammer-Syntax aufrufen:

addiere << >> (N, x, y);

Sie müssen auch Ihre malloc/ newund free/ deleteAnrufe auf cudaMallocManagedund ändern , cudaFreedamit Sie Speicherplatz auf der GPU zuweisen. Schließlich müssen Sie warten, bis eine GPU-Berechnung abgeschlossen ist, bevor Sie die Ergebnisse auf der CPU verwenden, mit denen Sie arbeiten können cudaDeviceSynchronize.

Die obige dreifache Klammer verwendet einen Gewindeblock und ein Gewinde. Aktuelle Nvidia-GPUs können viele Blöcke und Threads verarbeiten. Beispielsweise verfügt eine Tesla P100-GPU, die auf der Pascal-GPU-Architektur basiert, über 56 Streaming-Multiprozessoren (SMs), die jeweils bis zu 2048 aktive Threads unterstützen können.

Der Kernel-Code muss seinen Block- und Thread-Index kennen, um seinen Offset in den übergebenen Arrays zu finden. Der parallelisierte Kernel verwendet häufig eine Gitterschrittschleife , wie die folgende:

__global__

void add (int n, float * x, float * y)

{

   int index = blockIdx.x * blockDim.x + threadIdx.x;

   int stride = blockDim.x * gridDim.x;

   für (int i = Index; i <n; i + = Schritt)

     y [i] = x [i] + y [i];

}}

Wenn Sie sich die Beispiele im CUDA Toolkit ansehen, werden Sie feststellen, dass mehr zu beachten ist als die oben beschriebenen Grundlagen. Beispielsweise müssen einige CUDA-Funktionsaufrufe in checkCudaErrors()Aufrufe eingeschlossen werden. In vielen Fällen verwendet der schnellste Code auch Bibliotheken, z. B. cuBLASZuordnungen von Host- und Gerätespeicher und Kopieren von Matrizen hin und her.

Zusammenfassend können Sie Ihre Apps mit GPUs auf vielen Ebenen beschleunigen. Sie können CUDA-Code schreiben. Sie können CUDA-Bibliotheken aufrufen. und Sie können Anwendungen verwenden, die CUDA bereits unterstützen.