Information Coding / Computer Graphics, ISY, LiTH CUDA

Relevanta dokument
Information Coding / Computer Graphics, ISY, LiTH CUDA. En lösning för generella beräkningar. En introduktion: Programmingsmodell och språk

Information Coding / Computer Graphics, ISY, LiTH. Minnesaccess. Vitalt för prestanda! Minnestyper. Coalescing

Information Coding / Computer Graphics, ISY, LiTH. Compute shaders!! Framtiden för GPU computing eller sen efterapning av Direct Compute?

Teknik för avancerade datorspel!

Teknik för avancerade datorspel!

Parallellism i NVIDIAs Fermi GPU

LUNDS UNIVERSITET. Parallell exekvering av Float32 och INT32 operationer

Strategier för att utnytja parallella system. Peter Kjellström NSC Upplysning

TBSK03 Teknik för avancerade Datorspel. Jens Ogniewski Information Coding Group Linköpings universitet

Programmeringsteknik med C och Matlab

Grundläggande C-programmering del 2 Pekare och Arrayer. Ulf Assarsson

TDIU01 - Programmering i C++, grundkurs

Grundläggande C-programmering del 2 Pekare och Arrayer. Ulf Assarsson

Föreläsning 3. Programmering, C och programmeringsmiljö

Ulf Assarsson. Grundläggande C-programmering del 2 Pekare och Arrayer. Läromoment:

Programmering B med Visual C

Programmering av inbyggda system. Pekare och Arrayer. Ulf Assarsson. Originalslides av Viktor Kämpe

Tillämpad programmering

4 grundregler. Minneshantering. Problemet. Windows minkrav

Software Technology. Josef Svenningsson

... Funktionsanrop. Vad händer när man kör ett program?

Innehåll. Pekare Exempel

Programmering av inbyggda system. Kodningskonventioner. Viktor Kämpe

Besvara de elektroniska frågorna (se kurshemsidan). Läs kapitel i kursbok

Översikt Introduktion DST 1. Nicholas Wickström. IDE, Högskolan i Halmstad. N. Wickström

Värmedistribution i plåt

Innehåll. Pekare Exempel

F5: Högnivåprogrammering

Introduktion C-programmering

F5: Högnivåprogrammering

GU / Chalmers Campus Lindholmen Tentamen Programutveckling LEU 482 / TIG167

Minnets komponenter. Digitala System: Datorteknik. Programexekvering. Programexekvering. Enhet för utdata. Enhet för indata CPU.

Ett problem. Kontrollstrukturer och arrayer. Arrayer. Lösningen. Arrayer och hakparanteser. Exempel int[] results; results = new int[10]; // 0..

Fortsä'ning Pekare. Ulf Assarsson. Originalslides av Viktor Kämpe

Exempel. Arrayer. Lösningen. Ett problem. Arrayer och hakparanteser. Arrayer

Övning från förra gången: readword

Programsystemkonstruktion med C++: Övning 1. Karl Palmskog september 2010

En klass behöver både deklaration och definition. Daniel Aarno Globala funktioner och variabler är OK.

Grundkurs i programmering - intro

Repetition C-programmering

Innehåll. Resurshantering. Resource handles. Minnesallokering. Minnesallokering Exempel: allokering på stacken. 6. Resurshantering

Digitalteknik och Datorarkitektur 5hp

Att använda pekare i. C-kod

Grafikkort till parallella beräkningar

Operativsystem. Innehåll. Operativsystemets funktion. Vad är ett OS? Vart hittar men ett OS? OS hanterar processorns resurser

32 Bitar Blir 64 Sammanfattning

Den som bara har en hammare tror att alla problem är spikar

Programsystemkonstruktion med C++

Inledning. Vad är ett datorprogram, egentligen? Olika språk. Problemlösning och algoritmer. 1DV433 Strukturerad programmering med C Mats Loock

Datorarkitekturer med operativsystem ERIK LARSSON

Programmering i C++ Kompilering från kommandoraden

Programmering, grundkurs, 8.0 hp, Elektro, KTH, hösten Programmering: att instruera en maskin att utföra en uppgift, kräver olika språk:

2D1387 Programsystemkonstruktion med C++ Laboration 1: Grundläggande C++ 31 augusti 2005

Föreläsning 6: Metoder och fält (arrays)

GU / Chalmers Campus Lindholmen Tentamen Programutveckling LEU 482 / TIG167

printenv sort pager printenv grep args sort pager

Programmering i C++ EDA623 Typer. EDA623 (Föreläsning 4) HT / 33

Innehåll. Pekare Syntax

DD2387 Programsystemkonstruktion med C++ Tentamen 1 Tisdagen den 28 oktober 2014, 08:00-12:00

Arrayer. results

Miniprojekt: MEX och molekyldynamik

Kompilering och exekvering. Föreläsning 1 Objektorienterad programmering DD1332. En kompilerbar och körbar java-kod. Kompilering och exekvering

Elektroteknik MF1016 föreläsning 9 MF1017 föreläsning 7 Mikrodatorteknik

Föreläsning 3. Programmering, C och programmeringsmiljö

Programmering av inbyggda system. Pekare och Arrayer. Viktor Kämpe

Typkonvertering. Java versus C

Vad är en dator? Introduktion till datorer och nätverk. Pontus Haglund Institutionen för datavetenskap (IDA) 21 augusti 2018

2D1387 Programsystemkonstruktion med C++ Laboration 1: Grundläggande C++ 2 september 2006

Det finns många flaggor till g++,

Agenda. Arrayer deklaration, åtkomst Makron Flerdimensionella arrayer Initiering Strängar Funktioner och arrayer. Övningar nu och då

Datorarkitektur I. Tentamen Lördag 10 April Ekonomikum, B:154, klockan 09:00 14:00. Följande gäller: Skrivningstid: Fråga

Operativsystem Lektion 1. Lärare. Schema. Kurssajten Finns på adressen. Jan Erik Moström. Set Norman

Grundläggande datavetenskap, 4p

Skriv i mån av plats dina lösningar direkt i tentamen. Skriv ditt kodnummer längst upp på varje blad.

Minnet från processorns sida Datorteknik

Introduktion till hårdvara, mjukvara och operativsystem

GPGPU - General-Purpose computing on Graphics Processing Units

Parallellprogrammering i C++ 17 EDT621 Datorarkitekturer med Operativsystem Viktor Lindgren

Programmering, grundkurs, 8.0 hp HI1024, HI1900 etc., Tentamen TEN1. Måndagen den 10 januari 2011,

Datorarkitekturer med operativsystem ERIK LARSSON

Recap Mera om nya typer Kort Fält. Programmering. Sommarkurs Verónica Gaspes. IDE-sektionen.

Innehåll. Introduktion till objektorientering. OOP (objektorienterad programmering) Objekt, instanser, klasser

TENTAMEN CD5250. Objektorienterad programutveckling med C++, 5p. Datum: , Tid: 14:00-19:00

BMI = (vikt i kg) / (längd i m) 2. Lösningsförslag

Funktioner. Jan Erik Moström,

Boken?!?! Vad är ett program? Kompilerande-Interpreterande Programmeringsmiljö Hello World! Att programmera och ett enkelt program Variabler printf

Operativsystem ID1200/06 (ID2200/06 6hp) Tentamen :00-18:00

Grafiska pipelinens funktion

Föreläsning 1: Intro till kursen och programmering

Datastrukturer, algoritmer och programkonstruktion (DVA104, VT 2015) Föreläsning 6

Programmering av grafisk display

Programmering för språkteknologer II, HT2011. Rum

Programmering, grundkurs, 8.0 hp HI1024, TEN1. Fredagen den 2 mars 2012

Föreläsning 10. Pekare (Pointers)

Operativsystem (IS1350) :00-12:00

Kapitel 6 - Undantag

Föreläsning 1: Intro till kursen och programmering

int (*fp) (char, char*) //pekare till funktion som tar //argumenten (char, char*) och //returnerar int

Programmering av grafisk display

Tentamen PC-teknik 5 p Lösningar och kommentarer

Transkript:

24(83) Information Coding / Computer Graphics, ISY, LiTH CUDA En lösning för generella beräkningar. En introduktion: Programmingsmodell och språk Minnesareor och minnesaccess Delat minne Exempel 24(83)

CUDA = Compute Unified Device Architecture Utvecklat av NVidia Fungerar bara på NVidia-kort, G80 eller bättre GPU-arkitektur Designat för att dölja att hårdvarans egentligen är för grafik, och för att ge mer kontroll och flexibilitet 25(83)25(83)

Liknar shader-baserade lösningar: 1. Ladda upp data till GPU 2. Exekvera beräkningskärna 3. Ladda ner resultat 26(83)26(83)

Integrerad kod Källkoden till värdprogram och beräkningskärnor kan vara i samma källfil, skriva som ett enda program Betydande skillnad mot shaders (och OpenCL) där kärnan är separat och explicit laddas och kompileras av värden. Beräkningskärnor indentifieras med speciella modifierare i koden. 27(83)27(83)

CUDA Arkitektur och utvidgning av C för parallellbearbetning. Skapar ett stort antal trådar som körs parallellt /mer eller mindre). Mycket är precis som i grafik Du kan inte anta att alla trådar körs parallelt. De körs ett antal i taget: en warp (varp, syftar på vävning). Men nu ser det mer ut som ett vanligt C-program. Inget trassel med data som lagras som pixlar, som i GLSL. Vi kan jobba med vanliga arrayer 28(83)28(83)

Enkelt CUDA-exempel Ett fungerande, kompilerbart, körbart exempel #include <stdio.h> const int N = 16; const int blocksize = 16; global void simple(float *c) { c[threadidx.x] = threadidx.x; } int main() { int i; float *c = new float[n]; float *cd; const int size = N*sizeof(float); cudamalloc( (void**)&cd, size ); dim3 dimblock( blocksize, 1 ); dim3 dimgrid( 1, 1 ); simple<<<dimgrid, dimblock>>>(cd); cudamemcpy( c, cd, size, cudamemcpydevicetohost ); cudafree( cd ); for (i = 0; i < N; i++) printf("%f ", c[i]); printf("\n"); delete[] c; printf("done\n"); return EXIT_SUCCESS; } 29(83)29(83)

Enkelt CUDA-exempel Ett fungerande, kompilerbart, körbart exempel #include <stdio.h> const int N = 16; const int blocksize = 16; Kernel global void simple(float *c) { c[threadidx.x] = threadidx.x; } thread identifier int main() { int i; float *c = new float[n]; float *cd; const int size = N*sizeof(float); cudamalloc( (void**)&cd, size ); dim3 dimblock( blocksize, 1 ); dim3 dimgrid( 1, 1 ); simple<<<dimgrid, dimblock>>>(cd); Call kernel cudamemcpy( c, cd, size, cudamemcpydevicetohost ); cudafree( cd ); for (i = 0; i < N; i++) printf("%f ", c[i]); printf("\n"); delete[] c; printf("done\n"); return EXIT_SUCCESS; } Allocate GPU memory 1 block, 16 threads Read back data 30(83)30(83)

Modifierare för kodtyper Tre modifierare anger hur kod skall användas: global körs på GPU, startas av CPU. Detta är beräkningskärnans ingångspunkt. device är kod som körs på GPU host är kod som körs på CPU (default). CPU host myhostfunc() GPU device mydevicefunc(() global myglobalfunc(() 31(83)31(83)

Minneshantering cudamalloc(ptr, datasize) cudafree(ptr) Liknar CPUns minnesallokering, men görs av CPUn för att allokera på GPU cudamemcpy(dest, src, datasize, arg) arg = cudamemcpydevicetohost or cudamemcpyhosttodevice 32(83)32(83)

Körning av kärnan simple<<<griddim, blockdim>>>( ) (Mycket egendomlig syntax.) Grid är en grid av block. Varje block har nummer inom grid och varje tråd har nummer inom sitt block. Inbyggda variabler för kärnan: threadidx och blockidx blockdim och griddim (OBS, inget prefix som i GLSL.) 33(83)33(83)

Kompilera Cuda nvcc nvcc är nvidias kompilator, /usr/local/cuda/bin/nvcc Källfiler har suffix.cu Enklast möjliga kommandorad: nvcc simple.cu -o simple (Fler parametrar finns för bibliotek mm.) 34(83)34(83)

Kompilera Cuda för större tillämpningar nvcc och gcc i kombination nvcc för.cu-filer gcc för.c/.cpp etc Det går bra att blanda språk. Länkning måste inkludera C++-runtimebibliotek. Exempel: En C-fil, en CU-fil 35(83)35(83)

Exempel på multi-fil-kompilering Källfiler: cudademokernel.cu och cudademo.c nvcc cudademokernel.cu -o cudademokernel.o -c gcc -c cudademo.c -o cudademo.o -I/usr/local/cuda/include g++ cudademo.o cudademokernel.o -o cudademo -L/usr/local/ cuda/lib -lcuda -lcudart -lm Länka med g++ för att inkludera C++-runtime 36(83)36(83)

C/CUDA program code.cu CUDA-kompilering bakom scenen nvcc CPU binary PTX code PTX to target Target binary code 37(83)37(83)

Beräkningar med CUDA Organisation och åtkomst Blocks, threads... 38(83)38(83)

Warps En warp är det minsta antal trådar som processas parallellt i en CUDA-kapabel enhet. Detta antal är satt till 32. Vi behöver normalt inte tänka så mycket på warps utan i första hand tänka på block och threads. 39(83)39(83)

Processing organization 1 warp = 32 threads 1 kernel - 1 grid 1 grid - many blocks 1 block - 1 thread processor 1 block - many threads Använd många trådar och många block > 200 blocks rekommenderas. Antal trådar bör vara multipel av 32 40(83)40(83)

Fördelning av beräkningar över threads och blocks Hierarkisk modell Grid Block 0,0 Block 1,0 Block 2,0 Block 3,0 Block n,n Thread 0,0 Thread 1,0 Thread 2,0 Thread 3,0 Block 0,1 Block 1,1 Block 2,1 Block 3,1 Thread 0,1 Thread 1,1 Thread 2,1 Thread 3,1 Thread 0,2 Thread 1,2 Thread 2,2 Thread 3,2 griddim.x * griddim.y blocks Thread 0,3 Thread 1,3 Thread 2,3 Thread 3,3 BlockDim.x * blockdim.y threads 41(83)41(83)

Indexera data med thread/block-ids Beräkna index via blockidx, blockdim, threadidx Enkelt exempel, beräkna kvadrat av varje element (enbart kärnan): // Kernel that executes on the CUDA device global void square_array(float *a, int N) { int idx = blockidx.x * blockdim.x + threadidx.x; if (idx<n) a[idx] = a[idx] * a[idx]; } 42(83)42(83)

Värdprogram för kvadratexempel Sätt block size och grid size // main routine that executes on the host int main(int argc, char *argv[]) { float *a_h, *a_d; // Pointer to host and device arrays const int N = 10; // Number of elements in arrays size_t size = N * sizeof(float); a_h = (float *)malloc(size); cudamalloc((void **) &a_d, size); // Allocate array on device // Initialize host array and copy it to CUDA device for (int i=0; i<n; i++) a_h[i] = (float)i; cudamemcpy(a_d, a_h, size, cudamemcpyhosttodevice); // Do calculation on device: int block_size = 4; int n_blocks = N/block_size + (N%block_size == 0? 0:1); square_array <<< n_blocks, block_size >>> (a_d, N); // Retrieve result from device and store it in host array cudamemcpy(a_h, a_d, sizeof(float)*n, cudamemcpydevicetohost); // Print results and cleanup for (int i=0; i<n; i++) printf("%d %f\n", i, a_h[i]); free(a_h); cudafree(a_d); } 43(83)43(83)

Minnesaccess Vitalt för prestanda Minnestyper Coalescing Exampel på hur man kan använda delat minne 44(83)44(83)

Minnestyper Global Shared Constant (read only) Texture cache (read only) Local Registers Viktiga när man optimerar 45(83)45(83)

Globalt minne 400-600 cycles latency Använd lokalt delat minne som snabb mellanlagring Ordnade minnesaccesser (Coalescing) Kontinuerligt Starta på 2-potens-adress Addressera enligt trådnumrering Använd shared memory för att omorganisera data 46(83)46(83)

Använd shared memory för att minska antalet accesser av globalt minne Läs block till shared memory Processa Skriv tillbaka det som behövs Shared memory är en manuell cache Exempel: Matrismultiplikation 47(83)47(83)

Matrismultiplikation För att multiplicera två N*N-matriser måste varje element accessas N gånger Naiv implementation: 2N 3 globala minnesaccesser 48(83)48(83)

Matrismultiplikation Låt varje block generera en del av utdata Läs in de delar av matrisen som blocket behöver i shared memory. 49(83)49(83)

Destination element for thread Destination block for thread C A B All blocks on the same row in A are needed to produce the destination block And all blocks in the same column of C For every block, the thread reads one element matching the destination element For every block, we loop over the part of one row and column to perform that part of the computation What one thread reads is used by everybody in the same row (A) or column (B) 50(83)50(83)

Modifierad beräkningsmodell: Ladda upp data till globalt GPU-minne För valda delar: Ladda upp delar av data till shared memory Processa partiella data Skriv partiella data till globalt minne Läs ner resultatet till värden 51(83)51(83)

Synkronisering Så fort du gör något där en del av beräkningen beror av en annan så måste du synkronisera syncthreads() Typisk implementation: Läs till shared memory syncthreads() Processa shared memory synchthreads() Skriv resultatet till globalt minne. 52(83)52(83)

Accelering med coalescing Minnesöverföringar kan vara 10x snabbare om man kan addressera enligt coalescing-reglerna Exempel: Matristransponering Inga beräkingar Enbart minnesaccesser. 53(83)53(83)

Matristransponeing Naiv implementation global void transpose_naive(float *odata, float* idata, int width, int height) { unsigned int xindex = blockdim.x * blockidx.x + threadidx.x; unsigned int yindex = blockdim.y * blockidx.y + threadidx.y; } if (xindex < width && yindex < height) { unsigned int index_in = xindex + width * yindex; unsigned int index_out = yindex + height * xindex; odata[index_out] = idata[index_in]; } Hur kan detta vara dåligt? 54(83)54(83)

Matristransponeing Coalescing-problem Rad för rad och kolum för kolumn. Kolumnvis access är non-coalesced 55(83)55(83)

Matristransponering Lösning med coalescing Läs från globalt minne till shared memory Läs i ordning från globala minnet, godtycklig ordning till shared Skriv till globalt minne Skriv i ordning till globalt minne, godtycklig ordning från shadred 56(83)56(83)

Bättre matristransponering med CUDA global void transpose(float *odata, float *idata, int width, int height) { shared float block[block_dim][block_dim+1]; Shared memory for temporary storage // read the matrix tile into shared memory unsigned int xindex = blockidx.x * BLOCK_DIM + threadidx.x; unsigned int yindex = blockidx.y * BLOCK_DIM + threadidx.y; if((xindex < width) && (yindex < height)) { unsigned int index_in = yindex * width + xindex; block[threadidx.y][threadidx.x] = idata[index_in]; } Read data to temporary buffer syncthreads(); // write the transposed matrix tile to global memory xindex = blockidx.y * BLOCK_DIM + threadidx.x; yindex = blockidx.x * BLOCK_DIM + threadidx.y; if((xindex < height) && (yindex < width)) { unsigned int index_out = yindex * height + xindex; odata[index_out] = block[threadidx.x][threadidx.y]; } } Write data to tglobal memory 57(83)57(83)

Tumregler för coalescing Starta på multipel av 64 Addressera i ordning enligt trådnummer Man hoppa över vissa om man vill. Data bör vara i block om 4, 8 eller 16 bytes 58(83)58(83)

Texturminne Cachad Kan vara mycket snabbt att läsa från om mönstren är cache-vänliga. Texturfiltrering, linjär interpolation. Speciellt bra på att hantera 4 floats i taget (float4). cudabindtexturetoarray() binder data till en texturenhet. Programmeringen är ökänd för att vara knepigare. 59(83)59(83)

Portning till CUDA 1. Parallelliserbar CPU-algoritm. 2. Trivial (seriell) CUDA-implementation. 3. Dela upp i block och trådar. 4. Utnyttja shared memory. 60(83)60(83)

OpenCL OpenCL är en ny (2009) lösning för GPU Computing Uppbackat av Apple Gjort för att ge större frihet i hårdvara Inbyggt i MacOSX 10.6 Har inte CUDAs eleganta integration 61(83)61(83)

Var kan jag köra CUDA? Alla NVidia efter 8800 ( alla) Korsplattform: MS Windows, Linux, MacOSX. En hyfsat modern Mac är perfekt för OpenCL. (Förinstallerat.) Olympen + Southfork (helst Southfork) 62(83)62(83)

GLSL, CUDA eller OpenCL? GLSL är överlägset mest portabelt och lättast att installera. CUDA är elegant och integrerat men kräver specialinstallation och är kräset på hårdvara. OpenCL är portabelt, kräver specialinstallation överallt utom på OSX. => räkna inte ut GPGPU på shaders än 63(83)63(83)

Parallellprogrammering är framtiden All shaderprogrammering är parallellprogrammering. Så gott som all prestandaökning i framtiden kommer från parallelism. Vi fortsätter i TDDD56....och kanske i era projekt i denna kurs? 64(83)64(83)