C++

GPU-Programmierung mit C++

GPU-Programmierung mit C++

Überblick

In diesem Handbuch untersuchen wir die Leistungsfähigkeit der GPU-Programmierung mit C++. Entwickler können mit C++ eine unglaubliche Leistung erwarten, und der Zugriff auf die phänomenale Leistung der GPU mit einer Low-Level-Sprache kann einige der schnellsten derzeit verfügbaren Berechnungen liefern.

Bedarf

Obwohl jeder Computer, auf dem eine moderne Linux-Version ausgeführt werden kann, einen C++-Compiler unterstützen kann, benötigen Sie für diese Übung eine NVIDIA-basierte GPU. Wenn Sie keine GPU haben, können Sie eine GPU-gestützte Instanz in Amazon Web Services oder einem anderen Cloud-Anbieter Ihrer Wahl einrichten.

Wenn Sie sich für einen physischen Computer entscheiden, stellen Sie bitte sicher, dass die proprietären NVIDIA-Treiber installiert sind. Eine Anleitung dazu findet ihr hier: https://linuxhint.com/install-nvidia-drivers-linux/

Zusätzlich zum Treiber benötigen Sie das CUDA-Toolkit. In diesem Beispiel verwenden wir Ubuntu 16.04 LTS, aber es gibt Downloads für die meisten großen Distributionen unter der folgenden URL: https://developer.nvidia.com/cuda-downloads

Für Ubuntu würden Sie die .deb-basierter Download. Die heruntergeladene Datei hat kein .deb-Erweiterung standardmäßig, daher empfehle ich, sie in a umzubenennen .deb am ende. Dann können Sie installieren mit:

sudo dpkg -i Paketname.deb

Sie werden wahrscheinlich aufgefordert, einen GPG-Schlüssel zu installieren. Befolgen Sie in diesem Fall die Anweisungen, um dies zu tun.

Aktualisieren Sie anschließend Ihre Repositorys:

sudo apt-get update
sudo apt-get install cuda -y

Sobald dies erledigt ist, empfehle ich einen Neustart, um sicherzustellen, dass alles richtig geladen ist.

Die Vorteile der GPU-Entwicklung

CPUs verarbeiten viele verschiedene Ein- und Ausgänge und enthalten eine große Auswahl an Funktionen, um nicht nur die unterschiedlichsten Programmanforderungen zu erfüllen, sondern auch um unterschiedliche Hardwarekonfigurationen zu verwalten. Sie übernehmen auch Speicher, Caching, Systembus, Segmentierung und IO-Funktionalität und sind damit ein Alleskönner.

GPUs sind das Gegenteil – sie enthalten viele einzelne Prozessoren, die sich auf sehr einfache mathematische Funktionen konzentrieren. Aus diesem Grund verarbeiten sie Aufgaben um ein Vielfaches schneller als CPUs. Durch die Spezialisierung auf Skalarfunktionen (eine Funktion, die eine oder mehrere Eingaben benötigt, aber nur eine einzige Ausgabe zurückgibt), erreichen sie extreme Leistung auf Kosten extremer Spezialisierung special.

Beispielcode

Im Beispielcode fügen wir Vektoren zusammen. Ich habe eine CPU- und GPU-Version des Codes zum Geschwindigkeitsvergleich hinzugefügt added.
GPU-Beispiel.cpp Inhalt unten:

#include "cuda_runtime.h"
#einschließen
#einschließen
#einschließen
#einschließen
#einschließen
typedef std::chrono::high_resolution_clock Uhr;
#define ITER 65535
// CPU-Version der Vektor-Add-Funktion
void vector_add_cpu(int *a, int *b, int *c, int n)
int ich;
// Addiere die Vektorelemente a und b zum Vektor c
für (i = 0; i < n; ++i)
c[i] = a[i] + b[i];


// GPU-Version der Vektor-Add-Funktion
__global__ void vector_add_gpu(int *gpu_a, int *gpu_b, int *gpu_c, int n)
int i = threadIdx.x;
// Keine for-Schleife erforderlich, da die CUDA-Laufzeit
// wird diesen ITER mal einfädeln
gpu_c[i] = gpu_a[i] + gpu_b[i];

int main()
int *a, *b, *c;
int *gpu_a, *gpu_b, *gpu_c;
a = (int *)malloc(ITER * sizeof(int));
b = (int *)malloc(ITER * sizeof(int));
c = (int *)malloc(ITER * sizeof(int));
// Wir brauchen Variablen, auf die die GPU zugreifen kann,
// cudaMallocManaged stellt diese zur Verfügung
cudaMallocManaged(&gpu_a, ITER * sizeof(int));
cudaMallocManaged(&gpu_b, ITER * sizeof(int));
cudaMallocManaged(&gpu_c, ITER * sizeof(int));
für (int i = 0; i < ITER; ++i)
a[i] = i;
b[i] = i;
c[i] = i;

// Aufruf der CPU-Funktion und Zeitmessung
auto cpu_start = Clock::now();
vector_add_cpu(a, b, c, ITER);
auto cpu_end = Clock::now();
std::cout << "vector_add_cpu: "
<< std::chrono::duration_cast(cpu_end - cpu_start).Anzahl()
<< " nanoseconds.\n";
// Rufen Sie die GPU-Funktion auf und timen Sie es
// Die Dreifachwinkelbremse ist eine CUDA-Laufzeiterweiterung, die es ermöglicht
// Parameter eines zu übergebenden CUDA-Kernel-Aufrufs.
// In diesem Beispiel übergeben wir einen Threadblock mit ITER-Threads.
auto gpu_start = Clock::now();
vector_add_gpu <<<1, ITER>>> (gpu_a, gpu_b, gpu_c, ITER);
cudaDeviceSynchronize();
auto gpu_end = Clock::now();
std::cout << "vector_add_gpu: "
<< std::chrono::duration_cast(gpu_end - gpu_start).Anzahl()
<< " nanoseconds.\n";
// Geben Sie die GPU-funktionsbasierten Speicherzuweisungen frei
cudaFree(a);
cudaFree(b);
cudaFree(c);
// Die CPU-funktionsbasierten Speicherzuweisungen freigeben
befreie ein);
frei(b);
frei(c);
0 zurückgeben;

Makefile Inhalt unten:

INC=-I/usr/local/cuda/include
NVCC=/usr/local/cuda/bin/nvcc
NVCC_OPT=-std=c++11
alle:
$(NVCC) $(NVCC_OPT) GPU-Beispiel.cpp -o gpu-Beispiel
sauber:
-rm -f GPU-Beispiel

Um das Beispiel auszuführen, kompilieren Sie es:

machen

Führen Sie dann das Programm aus:

./gpu-Beispiel

Wie Sie sehen, läuft die CPU-Version (vector_add_cpu) deutlich langsamer als die GPU-Version (vector_add_gpu).

Wenn nicht, müssen Sie möglicherweise die ITER-Definition im GPU-Beispiel anpassen.cu zu einer höheren Zahl. Dies liegt daran, dass die GPU-Setup-Zeit länger ist als bei einigen kleineren CPU-intensiven Schleifen. Ich habe festgestellt, dass 65535 auf meiner Maschine gut funktioniert, aber Ihre Laufleistung kann variieren. Sobald Sie diesen Schwellenwert jedoch überschritten haben, ist die GPU dramatisch schneller als die CPU.

Fazit

Ich hoffe, Sie haben viel aus unserer Einführung in die GPU-Programmierung mit C . gelernt++. Das obige Beispiel bringt nicht viel, aber die demonstrierten Konzepte bieten einen Rahmen, mit dem Sie Ihre Ideen einbringen können, um die Leistung Ihrer GPU zu entfesseln.

Top 5 ergonomische Computermaus-Produkte für Linux
Verursacht längere Computernutzung Schmerzen im Handgelenk oder in den Fingern?? Leiden Sie unter steifen Gelenken und müssen ständig die Hände schütt...
So ändern Sie die Maus- und Touchpad-Einstellungen mit Xinput in Linux
Die meisten Linux-Distributionen werden standardmäßig mit der Bibliothek „libinput“ ausgeliefert, um Eingabeereignisse auf einem System zu verarbeiten...
Weisen Sie Ihre Maustasten mit der X-Mouse Button Control für verschiedene Software unterschiedlich zu
Vielleicht benötigen Sie ein Tool, mit dem sich die Steuerung Ihrer Maus bei jeder von Ihnen verwendeten Anwendung ändern kann. In diesem Fall können ...