Vad är CUDA? Parallell programmering för GPU: er

CUDA är en parallell datorplattform och programmeringsmodell som utvecklats av Nvidia för allmän databehandling på egna GPU: er (grafikbehandlingsenheter). CUDA gör det möjligt för utvecklare att påskynda datorintensiva applikationer genom att utnyttja kraften hos GPU: er för den parallelliserbara delen av beräkningen.

Även om det har funnits andra föreslagna API: er för GPU: er, till exempel OpenCL, och det finns konkurrenskraftiga GPU: er från andra företag, såsom AMD, dominerar kombinationen av CUDA och Nvidia GPU: er flera applikationsområden, inklusive djupinlärning, och är en grund för några av världens snabbaste datorer.

Grafikkort är förmodligen lika gamla som datorn - det vill säga om du ser IBM Monochrome Display Adapter från 1981 som ett grafikkort. År 1988 kunde du få ett 16-bitars 2D VGA Wonder-kort från ATI (företaget som så småningom förvärvades av AMD). År 1996 kan du köpa en 3D-grafikaccelerator från 3dfx Interactive så att du kan köra förstapersonsskytten Quake i full fart.

Även 1996 började Nvidia försöka konkurrera på 3D-acceleratormarknaden med svaga produkter, men lärde sig när det gick och 1999 introducerade den framgångsrika GeForce 256, det första grafikkortet som kallades en GPU. Vid den tiden var det främsta anledningen till att ha en GPU för spel. Det var inte förrän senare som folk använde GPU: er för matematik, naturvetenskap och teknik.

Ursprunget till CUDA

År 2003 presenterade ett forskargrupp under ledning av Ian Buck Brook, den första allmänt antagna programmeringsmodellen för att utöka C med dataparallella konstruktioner. Buck anslöt sig senare till Nvidia och ledde lanseringen av CUDA 2006, den första kommersiella lösningen för allmänna datorer på GPU: er.

OpenCL vs. CUDA

CUDA-konkurrenten OpenCL lanserades av Apple och Khronos-gruppen 2009, i ett försök att tillhandahålla en standard för heterogen databehandling som inte var begränsad till Intel / AMD-processorer med Nvidia-grafikprocessorer. Medan OpenCL låter attraktivt på grund av sin allmänna funktion har det inte presterat lika bra som CUDA på Nvidia GPU: er, och många djupa inlärningsramar stöder det inte eller stöder det bara som en eftertanke när deras CUDA-stöd har släppts.

CUDA-prestandaförbättring

CUDA har förbättrat och utvidgat sitt räckvidd genom åren, mer eller mindre i låst steg med förbättrade Nvidia GPU: er. Från och med CUDA version 9.2, med flera P100-server-GPU: er, kan du uppnå upp till 50 gånger prestandaförbättringar jämfört med processorer. V100 (visas inte i den här bilden) är ytterligare 3 gånger snabbare för vissa belastningar. Den tidigare generationen server-GPU: er, K80, erbjöd 5x till 12x prestandaförbättringar jämfört med CPU: er.

Nvidia

Hastighetsökningen från GPU: er har kommit på kort tid för högpresterande datorer. Den enkeltrådade prestandaförhöjningen av processorer över tid, vilket Moores lag föreslog skulle fördubblas var 18: e månad, har avtagit till 10 procent per år då chiptillverkare stött på fysiska gränser, inklusive storleksbegränsningar för chipmaskupplösning och chiputbyte under tillverkningsprocessen och värmebegränsningar på klockfrekvenser vid körning.

Nvidia

CUDA-applikationsdomäner

Nvidia

CUDA och Nvidia GPU: er har antagits i många områden som behöver hög prestanda för flytande punkt, vilket sammanfattas bildligt i bilden ovan. En mer omfattande lista innehåller:

  1. Beräkningsfinansiering
  2. Klimat-, väder- och havsmodellering
  3. Datavetenskap och analys
  4. Djupinlärning och maskininlärning
  5. Försvar och intelligens
  6. Tillverkning / AEC (arkitektur, teknik och konstruktion): CAD och CAE (inklusive beräkningsvätskedynamik, beräkningsstrukturmekanik, design och visualisering och elektronisk designautomatisering)
  7. Media och underhållning (inklusive animering, modellering och rendering; färgkorrigering och spannmålshantering; kompositering; efterbehandling och effekter; redigering; kodning och digital distribution; on-air grafik; on-set, recension och stereo verktyg och vädergrafik)
  8. Medicinsk bildbehandling
  9. Olja och gas
  10. Forskning: Högre utbildning och superdatorer (inklusive beräkningskemi och biologi, numerisk analys, fysik och vetenskaplig visualisering)
  11. Säkerhet och trygghet
  12. Verktyg och hantering

CUDA i djupinlärning

Djupinlärning har ett stort behov av datorhastighet. Till exempel, för att träna modellerna för Google Translate 2016 gjorde Google Brain och Google Translate-team hundratals en-veckors TensorFlow-körningar med GPU: er; de hade köpt 2000 grafikprocessorer av serverkvalitet från Nvidia för ändamålet. Utan grafikprocessorer hade dessa träningspass tagit månader snarare än en vecka att konvergera. För produktionsdistribution av dessa TensorFlow-översättningsmodeller använde Google ett nytt anpassat processchip, TPU (tensorbehandlingsenhet).

Förutom TensorFlow är många andra DL-ramar beroende av CUDA för deras GPU-stöd, inklusive Caffe2, CNTK, Databricks, H2O.ai, Keras, MXNet, PyTorch, Theano och Torch. I de flesta fall använder de cuDNN-biblioteket för djupneurala nätverksberäkningar. Det biblioteket är så viktigt för utbildningen av de djupa inlärningsramarna att alla ramar som använder en given version av cuDNN har i stort sett samma prestandanummer för motsvarande användningsfall. När CUDA och cuDNN förbättras från version till version, ser alla djupinlärningsramarna som uppdateras till den nya versionen prestationsvinsterna. Där prestandan tenderar att skilja sig från ram till ram är hur väl de skalas till flera GPU: er och flera noder.

CUDA-programmering

Nvidia

CUDA Toolkit

CUDA Toolkit innehåller bibliotek, felsöknings- och optimeringsverktyg, en kompilator, dokumentation och ett runtime-bibliotek för att distribuera dina applikationer. Den har komponenter som stöder djupinlärning, linjär algebra, signalbehandling och parallella algoritmer. I allmänhet stöder CUDA-bibliotek alla familjer med Nvidia GPU: er, men presterar bäst på den senaste generationen, till exempel V100, som kan vara 3 gånger snabbare än P100 för arbetsbelastningar för djupinlärningsträning. Att använda ett eller flera bibliotek är det enklaste sättet att dra nytta av GPU: er, så länge de algoritmer du behöver har implementerats i lämpligt bibliotek.

Nvidia

CUDA deep learning-bibliotek

Inom den djupa inlärningssfären finns det tre stora GPU-accelererade bibliotek: cuDNN, som jag nämnde tidigare som GPU-komponenten för de flesta öppna källkoder för djupinlärning; TensorRT, som är Nvidias högpresterande optimering och körtid för djupinlärningsinferens; och DeepStream, ett videoinferensbibliotek. TensorRT hjälper dig att optimera neurala nätverksmodeller, kalibrera för lägre precision med hög noggrannhet och distribuera de utbildade modellerna till moln, datacenter, inbäddade system eller fordonsproduktplattformar.

Nvidia

CUDA linjära algebra- och mattebibliotek

Linjär algebra stöder tensorberäkningar och därför djupinlärning. BLAS (Basic Linear Algebra Subprograms), en samling matrisalgoritmer som implementerades i Fortran 1989, har använts sedan dess av forskare och ingenjörer. cuBLAS är en GPU-accelererad version av BLAS och det bästa sättet att göra matrisberäkningar med GPU: er. cuBLAS antar att matriser är täta; cuSPARSE hanterar glesa matriser.

Nvidia

CUDA-signalbehandlingsbibliotek

Den snabba Fourier-transformationen (FFT) är en av de grundläggande algoritmerna som används för signalbehandling; det förvandlar en signal (som en ljudvågform) till ett frekvensspektrum. cuFFT är en GPU-accelererad FFT.

Codecs använder standarder som H.264, kodar / komprimerar och avkodar / dekomprimerar video för överföring och visning. Nvidia Video Codec SDK påskyndar denna process med GPU: er.

Nvidia

CUDA parallella algoritmbibliotek

De tre biblioteken för parallella algoritmer har alla olika syften. NCCL (Nvidia Collective Communications Library) är för skalning av appar över flera GPU: er och noder; nvGRAPH är för parallell grafanalys; och Thrust är ett C ++ - mallbibliotek för CUDA baserat på C ++ - standardmallbiblioteket. Thrust ger en rik samling av dataparallella primitiver som att skanna, sortera och minska.

Nvidia

CUDA kontra CPU-prestanda

I vissa fall kan du använda drop-in CUDA-funktioner istället för motsvarande CPU-funktioner. Till exempel kan GEMM-matrixmultiplikationsrutinerna från BLAS ersättas av GPU-versioner helt enkelt genom att länka till NVBLAS-biblioteket:

Nvidia

Grunderna för CUDA-programmering

Om du inte hittar CUDA-biblioteksrutiner för att påskynda dina program måste du försöka med CUDA-programmering på låg nivå. Det är mycket lättare nu än när jag försökte det först i slutet av 2000-talet. Bland annat finns det lättare syntax och det finns bättre utvecklingsverktyg tillgängliga. Mitt enda gräl är att den senaste CUDA-kompilatorn och den senaste C ++ -kompilatorn (från Xcode) på MacOS sällan är synkroniserade. Man måste ladda ner äldre kommandoradsverktyg från Apple och byta till dem med för xcode-selectatt få CUDA-koden att kompilera och länka.

Tänk till exempel på den här enkla C / C ++ -rutinen för att lägga till två matriser:

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

{  

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

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

}

Du kan förvandla den till en kärna som körs på GPU: n genom att lägga till __global__nyckelordet i deklarationen och ringa kärnan med hjälp av trippelfäste-syntaxen:

lägg till << >> (N, x, y);

Du måste också ändra dina malloc/ newoch free/ deletesamtal till cudaMallocManagedoch cudaFreeså att du tilldelar utrymme på GPU: n. Slutligen måste du vänta på att en GPU-beräkning ska slutföras innan du använder resultaten på CPU: n, som du kan uppnå med cudaDeviceSynchronize.

Trippelfästet ovan använder ett gängblock och en gänga. Nuvarande Nvidia GPU: er kan hantera många block och trådar. Till exempel har en Tesla P100 GPU baserad på Pascal GPU-arkitektur 56 Streaming Multiprocessors (SM), som alla kan stödja upp till 2048 aktiva trådar.

Kärnkoden måste känna till dess block- och trådindex för att hitta dess förskjutning i de passerade matriserna. Den parallelliserade kärnan använder ofta en rutnät- slinga, såsom följande:

__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 + = steg)

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

}

Om du tittar på proverna i CUDA Toolkit ser du att det finns mer att tänka på än de grunder jag täckte ovan. Till exempel måste vissa CUDA-funktionssamtal slås in i checkCudaErrors()samtal. I många fall kommer den snabbaste koden också att använda bibliotek, t.ex. cuBLAStillsammans med tilldelning av värd- och enhetsminne och kopiering av matriser fram och tillbaka.

Sammanfattningsvis kan du accelerera dina appar med GPU: er på många nivåer. Du kan skriva CUDA-kod; du kan ringa CUDA-bibliotek; och du kan använda applikationer som redan stöder CUDA.