C ++

GPU programiranje s C ++

GPU programiranje s C ++

Pregled

V tem priročniku bomo raziskali moč GPU programiranja s C++. Razvijalci lahko pričakujejo neverjetno zmogljivost s C ++, dostop do neverjetne moči grafičnega procesorja z nizkim nivojem pa lahko prinese nekaj najhitrejših trenutno izračuna.

Zahteve

Medtem ko lahko kateri koli stroj, ki lahko poganja moderno različico Linuxa, podpira prevajalnik C ++, boste za izvajanje te vaje potrebovali grafični procesor na osnovi NVIDIA. Če nimate GPU-ja, lahko v Amazon Web Services ali drugem ponudniku oblaka po vaši želji zavrtite primerek, ki ga poganja GPU.

Če izberete fizični stroj, preverite, ali imate nameščene lastniške gonilnike NVIDIA. Navodila za to najdete tukaj: https: // linuxhint.com / install-nvidia-drivers-linux /

Poleg gonilnika boste potrebovali komplet orodij CUDA. V tem primeru bomo uporabili Ubuntu 16.04 LTS, vendar so na voljo prenosi za večino večjih distribucij na naslednjem URL-ju: https: // razvijalec.nvidia.com / cuda-downloads

Za Ubuntu bi izbrali .prenos na osnovi deb. Prenesena datoteka ne bo imela datoteke .deb privzeto, zato priporočam, da jo preimenujete v .deb na koncu. Nato lahko namestite z:

sudo dpkg -i ime-paketa.deb

Verjetno boste pozvani, da namestite ključ GPG, in če je tako, sledite navodilom za to.

Ko to storite, posodobite svoje repozitorije:

posodobitev sudo apt-get
sudo apt-get namestite cuda -y

Ko končate, priporočam ponovni zagon, da zagotovite, da je vse pravilno naloženo.

Prednosti razvoja GPU

CPU obdelujejo veliko različnih vhodov in izhodov in vsebujejo širok izbor funkcij, ne samo za obravnavanje širokega izbora programskih potreb, temveč tudi za upravljanje različnih konfiguracij strojne opreme. Obvladujejo tudi pomnilnik, predpomnjenje, sistemsko vodilo, segmentiranje in funkcijo IO, zaradi česar so vse vrste poslov.

GPU so nasprotni - vsebujejo veliko posameznih procesorjev, ki so osredotočeni na zelo preproste matematične funkcije. Zaradi tega obdelajo naloge velikokrat hitreje kot CPE. S specializacijo za skalarne funkcije (funkcija, ki sprejme enega ali več vhodov, a vrne samo en izhod), dosežejo izjemne zmogljivosti za ceno ekstremne specializacije.

Primer kode

V primeru kode seštejemo vektorje. Za primerjavo hitrosti sem dodal različico kode za CPU in GPU.
gpu-primer.cpp vsebina spodaj:

#include "cuda_runtime.h "
#include
#include
#include
#include
#include
typedef std :: chrono :: high_resolution_clock Clock;
#define ITER 65535
// CPU različica funkcije vektorskega dodajanja
void vector_add_cpu (int * a, int * b, int * c, int n)
int i;
// V vektor c dodamo vektorska elementa a in b
za (i = 0; i < n; ++i)
c [i] = a [i] + b [i];


// GPU različica funkcije vektorskega dodajanja
__global__ void vector_add_gpu (int * gpu_a, int * gpu_b, int * gpu_c, int n)
int i = threadIdx.x;
// Ne za zanko, ker je izvajalno okolje CUDA
// bo potegnil to ITER-krat
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 * velikost (int));
b = (int *) malloc (ITER * velikost (int));
c = (int *) malloc (ITER * velikost (int));
// Potrebujemo spremenljivke, dostopne GPU,
// tako cudaMallocManaged to zagotavlja
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;

// Pokličite funkcijo CPU in določite čas
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).štetje ()
<< " nanoseconds.\n";
// Pokličite funkcijo GPU in določite čas
// Trikotne nosilce je razširitev izvajalnega okolja CUDA, ki omogoča
// parametri klica jedra CUDA, ki se posredujejo.
// V tem primeru prenašamo en blok niti z nitmi ITER.
auto gpu_start = Ura :: zdaj ();
vektor_add_gpu <<<1, ITER>>> (gpu_a, gpu_b, gpu_c, ITER);
cudaDeviceSynchronize ();
auto gpu_end = Ura :: zdaj ();
std :: cout << "vector_add_gpu: "
<< std::chrono::duration_cast(gpu_end - gpu_start).štetje ()
<< " nanoseconds.\n";
// Osvobodite dodelitve pomnilnika na podlagi funkcije GPU
cudaFree (a);
cudaFree (b);
cudaFree (c);
// Osvobodite dodelitve pomnilnika na osnovi funkcije CPU
brezplačno (a);
brezplačno (b);
brezplačno (c);
vrnitev 0;

Makefile vsebina spodaj:

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

Če želite zagnati primer, ga prevedite:

naredite

Nato zaženite program:

./ gpu-primer

Kot lahko vidite, različica CPU (vector_add_cpu) deluje precej počasneje kot različica GPU (vector_add_gpu).

V nasprotnem primeru boste morda morali prilagoditi opredelitev ITER v primeru gpu.cu na večje število. Razlog za to je, da je čas nastavitve GPU daljši od nekaterih manjših zank, ki intenzivno uporabljajo CPU. Ugotovil sem, da 65535 dobro deluje na mojem stroju, vendar se vaša kilometrina lahko razlikuje. Ko pa očistite ta prag, je GPU bistveno hitrejši od CPU.

Zaključek

Upam, da ste se veliko naučili iz našega uvajanja v programiranje GPU z C++. Zgornji primer ne prinaša veliko, vendar predstavljeni koncepti zagotavljajo ogrodje, ki ga lahko uporabite za vključitev svojih idej in sprostitev moči vašega grafičnega procesorja.

Kako obrniti smer drsenja miške in sledilne ploščice v sistemu Windows 10
Miška in Sledilna ploščicaRačunalništvo ni samo enostavno, ampak bolj učinkovito in manj zamudno. Življenja brez teh naprav si ne moremo predstavljati...
Kako spremeniti miškin kazalec in velikost, barvo in shemo kazalca v sistemu Windows 10
Kazalec miške in kazalec v operacijskem sistemu Windows 10 sta zelo pomembna vidika operacijskega sistema. To lahko rečemo tudi za druge operacijske s...
Brezplačni in odprtokodni igralni mehanizmi za razvoj iger Linux
Ta članek bo zajemal seznam brezplačnih in odprtokodnih igralnih mehanizmov, ki jih je mogoče uporabiti za razvoj 2D in 3D iger v Linuxu. Obstaja veli...