C ++

GPU programiranje sa C ++

GPU programiranje sa C ++

Pregled

U ovom ćemo vodiču istražiti snagu GPU programiranja s C-om++. Programeri mogu očekivati ​​nevjerojatne performanse sa C ++-om, a pristup fenomenalnoj snazi ​​GPU-a jezikom niske razine može rezultirati nekim od najbržih trenutno dostupnih izračuna.

Zahtjevi

Iako bilo koji stroj sposoban za pokretanje moderne verzije Linuxa može podržavati C ++ kompajler, trebat će vam GPU zasnovan na NVIDIA-i da biste slijedili ovu vježbu. Ako nemate GPU, možete zavrtiti instancu s GPU-om u Amazon Web Services ili drugom davatelju usluga u oblaku po vašem izboru.

Ako odaberete fizički stroj, provjerite imate li instalirane vlasničke upravljačke programe NVIDIA. Upute za to možete pronaći ovdje: https: // linuxhint.com / install-nvidia-drivers-linux /

Osim upravljačkog programa, trebat će vam CUDA alat. U ovom ćemo primjeru koristiti Ubuntu 16.04 LTS, ali dostupna su preuzimanja za većinu glavnih distribucija na sljedećem URL-u: https: // programer.nvidia.com / cuda-downloads

Za Ubuntu biste odabrali .preuzimanje na bazi deb. Preuzeta datoteka neće imati .deb proširenje prema zadanim postavkama, pa preporučujem da ga preimenujete u a .deb na kraju. Zatim možete instalirati sa:

sudo dpkg -i naziv paketa.deb

Vjerojatno će se od vas zatražiti da instalirate GPG ključ, a ako je tako, slijedite upute da biste to učinili.

Kada to učinite, ažurirajte svoja spremišta:

sudo apt-get ažuriranje
sudo apt-get install cuda -y

Kada završite, preporučujem ponovno pokretanje kako biste bili sigurni da je sve pravilno učitano.

Blagodati razvoja GPU-a

CPU obrađuju mnoge različite ulaze i izlaze i sadrže velik asortiman funkcija ne samo za rješavanje širokog asortimana programskih potreba već i za upravljanje različitim hardverskim konfiguracijama. Oni također obrađuju memoriju, predmemoriranje, sistemsku sabirnicu, segmentiranje i IO funkcionalnost, što ih čini dizalicom svih zanata.

GPU-ovi su suprotno - sadrže mnogo pojedinačnih procesora koji su usredotočeni na vrlo jednostavne matematičke funkcije. Zbog toga obrađuju zadatke mnogo puta brže od CPU-a. Specijalizacijom za skalarne funkcije (funkcija koja uzima jedan ili više ulaza, ali vraća samo jedan izlaz), postižu ekstremne performanse po cijenu ekstremne specijalizacije.

Primjer koda

U primjeru koda zbrajamo vektore. Dodao sam CPU i GPU verziju koda za usporedbu brzine.
gpu-primjer.cpp sadržaj ispod:

#include "cuda_runtime.h "
#include
#include
#include
#include
#include
typedef std :: chrono :: high_resolution_clock Clock;
#define ITER 65535
// CPU verzija vektorske funkcije dodavanja
void vector_add_cpu (int * a, int * b, int * c, int n)
int i;
// Dodajte vektorske elemente a i b u vektor c
za (i = 0; i < n; ++i)
c [i] = a [i] + b [i];


// GPU verzija funkcije vektorskog dodavanja
__global__ void vector_add_gpu (int * gpu_a, int * gpu_b, int * gpu_c, int n)
int i = threadIdx.x;
// Ne treba petlja za petlju jer je CUDA vrijeme izvođenja
// će ovo prebaciti ITER puta
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 * veličina (int));
b = (int *) malloc (ITER * veličina (int));
c = (int *) malloc (ITER * veličina (int));
// Trebamo varijable dostupne GPU-u,
// pa ih cudaMallocManaged pruža
cudaMallocManaged (& gpu_a, ITER * sizeof (int));
cudaMallocManaged (& gpu_b, ITER * sizeof (int));
cudaMallocManaged (& gpu_c, ITER * sizeof (int));
za (int i = 0; i < ITER; ++i)
a [i] = i;
b [i] = i;
c [i] = i;

// Pozovite CPU funkciju i odredite vrijeme
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).računati()
<< " nanoseconds.\n";
// Pozovite GPU funkciju i odredite vrijeme
// Trostruke kutne zagrade je CUDA runtime produženje koje omogućuje
// parametri poziva CUDA kernela koji se prosljeđuju.
// U ovom primjeru prenosimo jedan blok niti s ITER nitima.
auto gpu_start = Sat :: sada ();
vektor_add_gpu <<<1, ITER>>> (gpu_a, gpu_b, gpu_c, ITER);
cudaDeviceSynchronize ();
auto gpu_end = Sat :: sada ();
std :: cout << "vector_add_gpu: "
<< std::chrono::duration_cast(gpu_end - gpu_start).računati()
<< " nanoseconds.\n";
// Oslobodite raspodjelu memorije zasnovane na GPU funkciji
cudaFree (a);
cudaFree (b);
cudaFree (c);
// Oslobodite raspodjelu memorije zasnovane na CPU funkciji
besplatno (a);
besplatno (b);
besplatno (c);
return 0;

Makefile sadržaj ispod:

INC = -I / usr / local / cuda / include
NVCC = / usr / local / cuda / bin / nvcc
NVCC_OPT = -std = c ++ 11
svi:
$ (NVCC) $ (NVCC_OPT) gpu-primjer.cpp -o gpu-primjer
čist:
-rm -f gpu-primjer

Da biste pokrenuli primjer, kompajlirajte ga:

napraviti

Zatim pokrenite program:

./ gpu-primjer

Kao što vidite, CPU verzija (vector_add_cpu) radi znatno sporije od verzije GPU (vector_add_gpu).

Ako nije, možda ćete trebati prilagoditi ITER definiranje u primjeru gpu.cu na veći broj. To je zbog toga što je vrijeme postavljanja GPU-a dulje od nekih manjih petlji koje zahtijevaju CPU. Otkrio sam da 65535 dobro radi na mom stroju, ali vaša kilometraža može varirati. Međutim, nakon što očistite ovaj prag, GPU je dramatično brži od CPU-a.

Zaključak

Nadam se da ste puno naučili iz našeg uvoda u GPU programiranje s C-om++. Gornji primjer ne postiže puno, ali demonstrirani koncepti pružaju okvir koji možete koristiti za uključivanje svojih ideja kako biste oslobodili snagu vašeg GPU-a.

Vodič za Shadow of the Tomb Raider za Linux
Shadow of the Tomb Raider dvanaesti je dodatak seriji Tomb Raider - franšizi u akcijsko-avanturističkoj igri koju je stvorio Eidos Montreal. I kritiča...
Kako pojačati FPS u Linuxu?
FPS je kratica Okviri u sekundi. Zadatak FPS-a je mjerenje broja sličica u reprodukcijama video zapisa ili igranim izvedbama. Jednostavnim riječima, b...
Najpopularnije laboratorijske igre Oculus App
Ako ste vlasnik slušalica Oculus, tada morate biti sigurni u bočno učitavanje. Bočno učitavanje postupak je instaliranja nehranjenog sadržaja na vaše ...