Computerarchitectuur. Ch 4. Data-Level Parallelism

Vergelijkbare documenten
Computerarchitectuur. Ch 4. Data-Level Parallelism

Computerarchitectuur. Terugblik / discussie / oefenopgaven

Uitwerking oefententamen Computerarchitectuur December 2016

Computerarchitectuur. Hoofdstuk 3: Instruction-Level Parallelism

Computerarchitectuur. H&P App. C. Pipelining

Computerarchitectuur. H&P Ch 5. Thread-Level Parallelism

PyCuda. oftewel massief parallel rekenen. Jasper Spaans, Fox-IT PUN meeting

High Performance Computing

Centrale begrippen hoofdstuk 3. Waarom multiprogramming? Vandaag. processen proces state: running, ready, blocked,... Vragen??

College 13: Patterns (2)

informatica. hardware. overzicht. moederbord CPU RAM GPU architectuur (vwo)

Digitale en analoge technieken

High Performance Computing

college 2: Introductie

Computerarchitectuur. H&P Ch 2. Memory Hierarchy Design

Beter, Sneller, Mooier. Processoren 12 januari 2015

Computerarchitectuur 2016 Inleveropdracht 3: Exploiting Memory Hierarchies in Modern Systems

Computerarchitectuur. H&P Appendix A: Instruction Set Principles

Computerarchitectuur. H&P Appendix A: Instruction Set Principles

Tentamen Computersystemen

1 Aanvulling cosy deeltijd

Computerarchitectuur. App. B. Review of Memory Hierarchy

Concurrency. Gerard Tel / Jacco Bikker - november 2015 januari Welkom!

Computerarchitectuur en netwerken Toets 1 4 okt

Multi-core systemen. door Alexander Melchior

Studentnummer:... Opleiding:... a) Met welke term wordt het interface tussen software en hardware van een processor aangeduid?

Concurrency. Gerard Tel / Jacco Bikker - november 2015 januari Welkom!

Computerarchitectuur en netwerken. Memory management Assembler programmering

Computerarchitectuur. Hoofdstuk 1: Introductie

Computer Architectuur 2016 Handleiding bij de CUDA opdracht

College 4: Mechanismen

Cover Page. Author: Vu, Van Thieu Title: Opportunities for performance optimization of applications through code generation Issue Date:

From High-Level Language to language of the hardware

Examen Geavanceerde Computerarchitectuur

EECS 452 Lecture 10 Chip Multiprocessors. Instructor: Gokhan Memik EECS Dept., Northwestern University

Proeftentamen in1211 Computersystemen I (NB de onderstreepte opgaven zijn geschikt voor de tussentoets)

Examen Geavanceerde Computerarchitectuur

College 15: Monte-Carlo

6 Methodology. afgelopen twee jaar de grafische processor ontdekt als snelle en goedkope bron van verwerkingscapaciteit.

Java virtuele machine JVM

Computerarchitectuur en netwerken. Memory management Assembler programmering

De Parallelle Revolutie van GPU's en CPU's

Een interrupt is een hardwaremechanisme dat een extern apparaat in staat stelt om de CPU een signaal te sturen wanneer de I/O operatie voltooid is.

Herconfigureerbare Hardware in Ieders Bereik

Tim Mallezie Architectuur van besturingssystemen: Vraag A2.

von-neumann-architectuur Opbouw van een CPU Processoren 1 december 2014

Hoe werkt een rekenmachine?

Geheugenbeheer. ICT Infrastructuren 2 december 2013

Hardware Beginners. Processoren. Door Theo De Paepe

Een.NET-besturingssysteemtoolkit. Discovering Cosmos. Sijmen J. Mulder

Hoofdstuk 3: Processen: Beschrijving en Besturing. Wat is een proces? Waarom processen? Wat moet het OS ervoor doen? Is het OS zelf een proces?

computerarchitectuur antwoorden

Deel 1: Arduino kennismaking. Wat is een microcontroller, structuur van een programma, syntax,

Concurrency. Gerard Tel / Jacco Bikker - november 2015 januari Welkom!

Nederlandse samenvatting (Dutch summary)

De Arduino-microcontroller in de motorvoertuigentechniek (2)

De computer als processor

Inhoudsopgave. Optimalisatie van de mmips. Forwarding optie 1. Design flow. implementation

Gelijktijdigheid: Wederzijdse Uitsluiting & Synchronisatie Concurrency: Mutual Exclusion & Synchonization (5e ed: , Appendix A.

Microcontrollers Introductie INLMIC Jesse op den Brouw INLMIC/

n-queens minimale dominantie verzamelingen Chessboard Domination on Programmable Graphics Hardware door Nathan Cournik

College 10: OpenCL (1)

De AT90CAN microprocessor van ATMEL in de motorvoertuigentechniek (2)

Flex_Rooster WERKBOEK. INTRODUCTIE iseries. Dit werkboek is eigendom van ICS opleidingen en mag niet worden meegenomen.

Examen computerarchitectuur

Cover Page. The handle holds various files of this Leiden University dissertation

Tentamen Computerorganisatie in aug. 1999, uur. N.B.: Dit tentamen bestaat uit 30 opgaven Totaal aantal bladzijden: 9

Inhoud vandaag. Interrupts. Algemeen ARM7 AIC

Assembly en Assemblers. Processoren 5 januari 2015

Inleiding Practicum Operating Systems

OPTIMALISATIE VAN MPEG-4-WAVELETCODE VOOR DE TRIMEDIAPROCESSOR

11011 Processor MMI Intro. Binaire representatie. Computer: Logische opbouw (Von Neumann) 3-input 1-hot detector.

Proeftentamen in1211 Computersystemen I (Opm: de onderstreepte opgaven zijn geschikt voor de tussentoets)

OpenVPN(-NL) Performance. Jan Just Keijser 9 November 2017

Van Poort tot Pipeline. Ben Bruidegom & Wouter Koolen-Wijkstra AMSTEL Instituut Universiteit van Amsterdam

Vraag 1 (2 punten) (iii) Een lees-opdracht van virtueel adres 2148 seg 0, offset idem

Tweede Toets Concurrency 2 februari 2017, , Educ-β.

Beter, Sneller, Mooier. Processoren 27 maart 2012

Digitale technieken Deeltoets II

Onafhankelijke verzamelingen en Gewogen Oplossingen, door Donald E. Knuth, The Art of Computer Programming, Volume 4, Combinatorial Algorithms

Hoofdstuk 7. Computerarchitectuur

2 Algemene opbouw van een computersysteem

' Het tentamen is gesloten boek, dus het is niet toegestaan om het tekstboek, slides of eigen gemaakte aantekeningen te gebruiken.

Opgave Tussentijdse Oefeningen Jaarproject I Reeks 4: Lcd Interface & Files

ICT Infrastructuren: Processen en Threads. 18 november 2013 David N. Jansen

Welke wordt het? Ga je voor snelheid, of wordt het een minder dure uitgave om het nieuwe millennium in te gaan.

Geheugen en Adressering. Binding. Binding (2) Logische en Fysieke adresruimten. relocatie register. Dynamic loading

Hardware. Word. Anna van Kommer M3A

Computerarchitectuur en Netwerken. Computerarchitectuur

ASUS DESKTOP GT51CH-BE016T 2 099,00. Kenmerken COMPUTRADE. Artikelcode : ITASGT51CHBE016

Uitleg. Welkom bij de Beverwedstrijd Je krijgt 15 vragen, die je in maximaal 45 minuten moet beantwoorden.

Memory Management. Virtual Memory. Eisen Memory Management. Verdelen geheugen over meerdere processen

MSI DESKTOP INFINITE 8RC-259EU 1 499,00. Kenmerken. D-Ware. Artikelcode : ITMIINFINITE259

IN1805 I Operating System Concepten

College 11: Game Engines

Studiewijzer BACHELOR INFORMATICA

4EE11 Project Programmeren voor W. College 2, , Blok D Tom Verhoeff, Software Engineering & Technology, TU/e

Digitale technieken Microprocessoren

Uitwerking Tentamen Operating Systems Maandag 15 juni 2015 P1 P2 P3 P4 P5 P1 P3 P5 P4 P2 P1 P3 P5 P3. Opgave 1

Asus vivobook N705FD-GC064T-BE 1 349,00. Kenmerken. Artikelcode : ITASN705FNGC064

Transcriptie:

Computerarchitectuur Ch 4. Data-Level Parallelism Kristian Rietveld http://ca.liacs.nl/

Data-Level Parallelism Nu we de limieten hebben gezien van parallelisme tussen instructies, kunnen we parallelisme 'vinden' in data? - Data-level parallelism - Het draait hier om stukken data die in parallel kunnen worden verwerkt. Voorbeelden waar DLP te vinden is: - Matrix codes (wetenschappelijke codes) Image & video processing Sound processing...

Data-Level Parallelism (2) Hoe kunnen we data-level parallelism implementeren? Met behulp van multi-cores: thread-level parallelism. Zie ook hoofdstuk 5. Zouden we een instructie dezelfde operatie kunnen laten toepassen op meerdere elementen tegelijkertijd? - Single Instruction Multiple Data (SIMD)

SIMD Het idee van SIMD is dat we steeds 1 instructie specificeren die werkt op meerdere data-elementen in parallel. Deze start dus meerdere operaties per instructie. Minder controle logica nodig, beter energiegebruik (vandaar vaak te vinden in smart phones e.d.). Programma's blijven sequentieel en een parallelle speedup wordt gehaald door parallelle data operaties. - Prettig voor de programmeurs; het is sequentieel makkelijker denken dan parallel.

SIMD (2) We zullen 3 vormen van SIMD bekijken: 1) Vectorarchitecturen 2) Multimedia SIMD extensies (MMX ('96), SSE, AVX (allen Intel), AltiVec (PowerPC), NEON (ARM)) 3) Graphics Processing Units (GPUs)

Vector Architectures De ontwikkeling van klassieke vectorarchitecturen gaat terug tot de Cray-I (1976). In het boek wordt een VMIPS ISA geïntroduceerd, dat lijkt op de ISA van Cray-I: Grote register file, met vector registers. - 8 registers met elk 64 elementen. - Veel read/write ports. Vector Functional Unit, volledig gepipelined. Vector instructies die werken op volledige vectoren. - addvv.d V1,V2,V3 Optelling van vectoren V2, V3, resultaat naar V1. - addvs.d V1,V2,F0 Tel scalair F0 op bij elk element V2, resultaat naar V1.

Vectorinstructies Vectorinstructies kunnen op verschillende manieren worden geïmplementeerd. Het aantal beschikbare functional units kan verschillen: - Het is eenvoudig om brede units te maken die draaien op lage kloksnelheid. Tussen elementen binnen eenzelfde instructie kunnen geen hazards ontstaan, dus geen checks nodig (bij superscalar wel). - Of smalle units en pipelining toepassen. De Cray-I had 12 pipelined functional units. In het algemeen kan een hoge bandbreedte worden gehaald zonder gebruik te maken van dynamic scheduling.

Vectorinstructies (2) We bekijken een voorbeeld (DAXPY): Y = a * X + Y - We gaan uit van vectoren met lengte 64. L.D DADDIU Loop: L.D MUL.D L.D ADD.D S.D DADDIU DADDIU DSUBU BNEZ F0, a R4,Rx,#512 F2,0(Rx) F2,F2,F0 F4,0(Ry) F4,F4,F2 F4,0(Ry) Rx,Rx,#8 Ry,Ry,#8 R20,R4,Rx R20,Loop

Vectorinstructies (2) We bekijken een voorbeeld (DAXPY): Y = a * X + Y - We gaan uit van vectoren met lengte 64. L.D DADDIU Loop: L.D MUL.D L.D ADD.D S.D DADDIU DADDIU DSUBU BNEZ F0, a R4,Rx,#512 F2,0(Rx) F2,F2,F0 F4,0(Ry) F4,F4,F2 F4,0(Ry) Rx,Rx,#8 Ry,Ry,#8 R20,R4,Rx R20,Loop L.D LV MULVS.D LV ADDVV.D SV F0,a V1,Rx V2,V1,F0 V3,Ry V4,V2,V3 V4,Ry

Vectorinstructies (3) Loops die mbv vectorinstructies kunnen worden geschreven noemen we vectorizable loops. Pipeline interlocks: - In de MIPS code moet elke add wachten voor mul en elke sd voor add. - In VMIPS: de vectorinstructie heeft alleen een stall voor het eerste element, daarna blijft de pipeline gevuld. - We zien dus een pipeline stall per vector instructie ipv per vector element. Forwarding in vector architecturen: - Forwarding kan worden toegepast tussen instructies die op dezelfde elementen opereren: men noemt dit chaining.

Terminologie Vector functional units hebben vaak meerdere parallelle pipelines: dit noemt men lanes. - Per clock cycle worden 2 of meer resultaten geproduceerd. Een convoy is een set van vectorinstructies die samen kunnen worden uitgevoerd. Middels chaining kan een vectoroperatie worden gestart zodra de eerste individuele elementen beschikbaar zijn. - Instructies die RAW hazards hebben kunnen zo toch in dezelfde convoy zitten. Chime: de tijd die nodig is om een convoy te verwerken. - Exacte tijd afhankelijk van target architectuur. Executietijd kan worden geschat door het aantal convoys te tellen (m convoys -> m chimes). - Hier wordt wel uitgegaan van lange vectoren.

Multiple lanes Taken from Computer Architecture: A Quantitative Approach, fifth edition. Fig. 4.4.

Multiple lanes (2) Taken from Computer Architecture: A Quantitative Approach, fifth edition. Fig. 4.5.

Masking Loops met if-condities kunnen we niet zomaar vectoriseren. We moeten wel de control dependence correct afhandelen. for (i = 0; i < 64; i++) if (X[i]!= 0) X[i] = X[i] Y[i]; Vaak wordt dit opgelost middels mask registers, een Boolean vector. - Het Boolean-element geeft telkens aan of een operatie voor dat element wel of niet moet worden uitgevoerd. - Elementen waarvoor de mask nul is kosten nog wel executietijd Vaak draait de loop nog steeds sneller dan een scalar (non-vector) variant.

Gather/Scatter Bij een vector-load laden we elementen die achter elkaar in het geheugen staan of volgens een vaste stride. Wat nu in het geval van indirectie? - Dus de array-indices om te benaderen staan in een andere array/vector. for (i = 0; i < n; i++) A[K[i]] = A[K[i]] + C[M[i]]; Hiervoor bestaan er speciale gather/scatter instructies: - Gather: load aan de hand van een index vector. - Scatter: tegenovergestelde operatie.

Multimedia SIMD Extensions

Multimedia SIMD Vele general-purpose processoren bevatten multimedia SIMD extensies. Introductie MMX in 1996. Wat gebeurde er? - x86 had toentertijd al 64-bit floating-point registers. - Veel graphics gebruikten 8-bit pixels. - Met MMX werd het mogelijk om via de 64-bit FP registers ook 8 8-bit of 4 16-bit operaties tegelijkertijd uit te voeren. In feite werken multimedia SIMD instructies op kleine vectoren. - Daarnaast ontbreken vele geavanceerde functionaliteiten van vectorarchitecturen, zoals strided vector load, scatter/gather.

Multimedia SIMD (2) Waarom nuttig / waarom geïntroduceerd? Er hoeft maar weinig aan bestaande ALU te worden toegevoegd, dus goedkoop om te implementeren. Door de kleine vectoren zijn er ook (veel) minder hoge eisen aan geheugenbandbreedte vergeleken met vectorachitecturen. Het doel was om via hand-gecodeerde libraries programma's te versnellen. - Er zijn compilers die vectorcode kunnen genereren, maar automatische vectorisatie is zeer beperkt. - Dit alles blijft toch handwerk... en zelfs dan moeilijk om winst te halen.

Multimedia SIMD (3) Een evolutie van SIMD: MMX, 1996. - 64-bit vectors. Pentium Pro / Pentium II era. SSE (Streaming SIMD Extensions), 1999. - Aparte register set, 128-bits. Pentium III era. - SSE2 2001, SSE3 2004, SSE4, 2007. AVX (Advanced Vector Extensions), 2010. - 256-bit vectors. Intel core era. - AVX2 voegt een gather instructie toe, maar geen scatter. Verwacht: AVX met 512-bit en later 1024-bit vectors. In ARM hebben we NEON, PowerPC had AltiVec.

Multimedia SIMD (4) Hoe programmeren we met behulp van SIMD extensies? Je kunt zelf assembly code schrijven. Iets eenvoudiger: gebruik maken van intrinsics. - Dit zijn eigenlijk de SIMD instructies verpakt als C functies, zodat je deze in C programma's kunt gebruiken zonder zelf inline assembly te schrijven. - Compiler zorgt voor een verdere vertaling naar assembly. - Zie verder het practicum. Als je peak performance wilt halen, blijf je aangewezen op assembly om zelf de instructievolgorde te tunen, enz.

Roofline Model Met behulp van het roofline model kunnen we de potentiële performance van verschillende SIMD architecturen vergelijken. We maken één grafiek, waarin we afbeelden: - Floating-point performance (peak) - Memory performance (max. bandbreedte) - Arithmetic intensity (FLOPS / bytes retrieved from memory) Taken from Computer Architecture: A Quantitative Approach, fifth edition. Fig. 4.10.

Roofline Model (2) Taken from Computer Architecture: A Quantitative Approach, fifth edition. Fig. 4.5. Diagonaal: berekening is memory-bound. Vlakke lijn: berekening is compute-bound

Graphics Processing Units

GPUs Waar zijn GPUs vandaan gekomen? - Eigenlijk vanuit een hele andere hoek. - Volledig ontworpen voor graphics. Begon met 3dFX eind jaren 90. Wat gebeurt er allemaal bij het renderen van 3-d graphics? - 3-d modellen opgebouwd uit polygonen / driehoeken. Coördinaattransformaties. Driehoeken uitlijnen op een grid van pixels. Driehoeken inkleuren. Driehoeken voorzien van schaduw / textures. Allemaal (eenvoudige) data parallele taken!

GPUs (2) GPUs zijn in feite ontworpen voor het uitvoeren van dezelfde taken op zeer veel data-elementen. - In het bijzonder eenvoudige taken: dus simpele programma's. Op een gegeven moment is men gaan kijken of de GPU ook buiten de graphics kon worden toegepast. - Matrix berekeningen doen via OpenGL textures (midden 2000). - Shaders programmeren. - En met de introductie van CUDA en OpenCL werd het gebruik van GPUs buiten graphics echt serieus. GPGPU programming: General Purpose GPU programming. Door CUDA heeft NVidia een zeer grote voorsprong wat betreft GPGPU programming.

GPUs (3) Vergeleken met CPUs is een GPU totaal anders georganiseerd. - Minder control logic. - Veel meer functional units. - Moderne kaarten hebben > 3000 simpele cores. De grootste moeilijkheid bij het begrijpen van GPUs is alle verschillende jargon die wordt gebruikt. - Het boek biedt een tabel aan met de NVidia-termen en de meer klassiekere benamingen die het boek gebruikt.

GPU programmeren Hoe programmeren we GPUs? De GPU is een aparte kaart binnen een computersysteem en wordt aangestuurd door de CPU (host). We hebben een library nodig om de GPU aan te sturen: - CUDA of OpenCL. We schrijven functies die op de GPU zullen worden uitgevoerd ( kernels ). Het geheugen van de GPU is apart, we moeten expliciet data tussen de CPU en GPU geheugens verplaatsen.

Werkverdeling Wanneer alles klaar staat, starten we duizenden threads op, die dezelfde kernel gaan uitvoeren. - Maar ieder op andere data! - Om threads uit te kunnen voeren, worden deze gegroepeerd in groepen van 32 threads (warps). - SIMT: Single Instruction Multiple Threads. Speciale manier om het werk te verdelen: - We starten een grid dat bestaat uit een aantal thread blocks. - Een thread block wordt toegewezen aan een bepaalde processor. - Een thread block bestaat uit een gegeven aantal threads, die in groepjes van 32 op een processor worden uitgevoerd.

Werkverdeling (2) Taken from Computer Architecture: A Quantitative Approach, fifth edition. Fig. 4.13.

Structuur GPU Een streaming multiprocessor (SM) kan 32 threads (een warp) tegelijkertijd uitvoeren. - Eigenlijk een 32-lane SIMD processor. - Elk van de 32 threads voert steeds dezelfde instructie uit. Een SM krijgt een geheel thread block toegewezen. - De hardware kan automatisch wisselen tussen blokken van 32 threads binnen hetzelfde thread block. - Multithreading wordt gebruikt om geheugen latency te verbergen! - Het boek noemt een SM een multithreaded SIMD processor. Een GPU bestaat uit meerdere streaming multiprocessors. - En bevat een thread block scheduler om thread blocks toe te wijzen aan SMs. - We zien hier dus terug: multi-core, multi-threading en SIMD.

Structuur GPU (2) Taken from Computer Architecture: A Quantitative Approach, fifth edition. Fig. 4.15.

Structuur GPU (3) Taken from Computer Architecture: A Quantitative Approach, fifth edition. Fig. 4.14.

NVIDIA Fermi architectuur Structuur van een SM. Twee sets van 16 SIMD lanes. Twee schedulers & dispatch units. Er worden telkens 2 threads gekozen, van ieder wordt een instructie naar een SIMD lane gestuurd. Dit gebeurt iedere 2 clock cycles. Taken from Computer Architecture: A Quantitative Approach, fifth edition. Fig. 4.19.

NVIDIA Fermi architectuur (2) Taken from Computer Architecture: A Quantitative Approach, fifth edition. Fig. 4.20.

GTX 980 Maxwell microarchitectuur 2048 CUDA cores Links een GM204. 4 Graphics Processing Clusters. 16 SMs Source: GeForce GTX 980 Whitepaper

Per SM: 128 CUDA cores. Per SM: 4 warp schedulers. Een warp scheduler kan 2 instructies per per warp per clock cycle dispatchen. DP units niet weergegeven (4 per SM). Source: GeForce GTX 980 Whitepaper

Source: NVIDIA P100 Architecture Whitepaper NVIDIA Pascal microarchitectuur. 3840 CUDA cores (Pieksnelheid ~10 TFLOPS, single-precision) Ter vergelijking: om 1 TFLOPS te behalen was in 1996 nog een grote supercomputer nodig.

Branching in GPUs Bij het uitvoeren van 32 threads, moeten alle threads steeds dezelfde instructie uitvoeren. Hoe gaat dat met if-statements? Waar de helft van de threads true heeft en de andere helft false? - Predicated instructies: true -threads slaan het resultaat van de berekening wel op, false -threads niet. Conditional branches in het algemeen: - Threads die de branch wel nemen voeren die uit, de andere threads wachten tot de control flow weer samenkomt. - Komt de efficientie dus niet ten goede. - Uitgebreide branching op GPUs vermijden.

Organisatie van het geheugen Elke SM heeft een on-chip lokaal geheugen ( shared memory ) dat door threads binnen eenzelfde thread block kan worden gedeeld. Daarnaast is er het normale off-chip GPU geheugen. - Elke thread heeft daarin wat prive opslag voor een stack, etc. - Om dit te versnellen wordt een kleine cache gebruikt. Er is geen hele grote cache: - Het doel van de cache is in het algemeen niet om latency te verbergen. - Bandbreedte wordt gekozen boven latency en latency wordt verborgen via multithreading. - In plaats van transistoren voor grote caches in te zetten, worden deze ingezet voor meer functional units.

Organisatie van het geheugen (2) Taken from Computer Architecture: A Quantitative Approach, fifth edition. Fig. 4.18.

Organisatie van het geheugen (3) Bij het optimaliseren van GPU codes komt vaak de term coalescing langs. Stel er wordt een load instructie uitgevoerd, dan voeren alle threads die tegelijkertijd uit. Er is speciale hardware die nagaat of de adressen van de load instructies van de verschillende threads binnen hetzelfde geheugenblok vallen. Wanneer dit zo is, worden al deze loads samengenomen in 1 load request dat naar het geheugen gaat. - Bandbreedte gaat hierdoor omhoog, overhead omlaag. Datastructuren worden zo opgeslagen zodat er gebruik kan worden gemaakt van coalescing.

Gebruiken van CUDA Hoe programmeren we zelf een GPU met behulp van CUDA? We maken gebruik van een speciale superset van C/C++; deze bevat speciale CUDA-extensies. - Source code geven we vaak de extensie ".cu". Hierdoor moeten we gebruik maken van een speciale C/C++compiler die in de CUDA Toolkit zit: nvcc. Met behulp van deze extensies schrijven we een of meerdere "kernels" die moeten gaan draaien op de GPU. Tevens moeten we de data transfers tussen de CPU en GPU regelen.

Data transfer Speciale functies om "device memory" te alloceren en data te kopieren tussen CPU en GPU: /* CPU */ float *b = (float *)malloc(n * sizeof(float)); cudamalloc(&b_dev, N * sizeof(float)); cudamemcpy(b_dev, b, N * sizeof(float), cudamemcpyhosttodevice); /* en de andere kant op */ cudamemcpy(b, b_dev, N * sizeof(float), cudamemcpydevicetohost); cudafree(b_dev);

Kernel schrijven Denk eerst na hoe je het werk over de threads wilt verdelen. Daarna kun je de kernel schrijven. Bijvoorbeeld voor een matrix-manipulatie waar we een element met 2 vermenigvuldigen en een waarde uit een vector erbij optellen. We kunnen er voor kiezen om te beginnen voor om voor elk matrix element een thread te maken. global void add_vec_gpu1(float A[N][N], const float b[n]) { int i = blockidx.x * blockdim.x + threadidx.x; int j = blockidx.y * blockdim.y + threadidx.y; } A[i][j] = A[i][j] * (float)2 + b[i]; Met behulp van shared kun je variabelen (ook arrays) declareren die worden gedeeld tussen alle threads in een thread block.

Kernel opstarten Om de kernel op te starten moeten we aangegeven uit hoeveel threads een thread block bestaat en uit hoeveel blocks een grid bestaat. Dit mag worden aangegeven in 1, 2 of 3 dimensies. Voor ons voorbeeld: we hebben een thread per matrix element nodig. Stel we gebruiken 16 x 16 = 256 threads per thread block. We hebben dan een grid van N/16 bij N/16 threads blocks. We starten dan de kernel als volgt op: dim3 thread_block_size(16, 16); dim3 n_thread_blocks(n/thread_block_size.x, N/thread_block_size.y); add_vec_gpu1<<<n_thread_blocks, thread_block_size>>>(a_dev, b_dev);

Compileren en testen We kunnen het programma nu compileren en testen. nvcc -O3 -o test test.cu Bij het compileren wordt er automatisch PTX assembly en een PTX binary gemaakt aan de hand van de kernel codes. Je kunt het programma uitvoeren door gewoon "./test" op te starten. Je kunt het programma ook onder "nvprof" uitvoeren, dit geeft je allerlei statistieken: nvprof./test

Hoe nu verder Ok, het werkt en hoe nu verder? Nu begint het echte analyseren en optimaliseren. Bijvoorbeeld: de thread blocks anders inrichten. We kiezen ervoor om per thread block 512 matrix elementen in dezelfde rij te verwerken. En verder: alle non-coalesced memory accesses proberen te elimineren.

Loop-Level Parallelism

Loop-Level Parallelism Voor DLP hebben we het liefst loops die volledig in parallel kunnen worden uitgevoerd. - Alle iteraties zijn onafhankelijk van elkaar. - Er zijn geen loop-carried dependences. for (i = 0; i < 1000; i++) x[i] = x[i] + s;

Loop-Level Parallelism (2) Soms valt er niets aan loop-carried dependences te doen, zoals in dit voorbeeld. - Eerste statement legt de volgorde van de iteraties geheel vast; A[i] wordt gelezen die in de voorgaande iteratie is gegenereerd. - Stel we zouden alleen de dependence op A[i+1] hebben tussen statement 1 en 2, dan zouden de loop iteraties wel in parallel kunnen worden uitgevoerd. Dit komt omdat deze dependence binnen eenzelfde loop iteratie valt. for (i = 0; i < 100; i++) { A[i+1] = A[i] + C[i]; B[i+1] = B[i] + A[i+1]; }

Loop-Level Parallelism (3) for (i = 0; i < 100; i++) { A[i] = A[i] + B[i]; B[i+1] = C[i] + D[i]; } Soms kan met een transformatie een loop worden omgezet in een loop die wel in parallel kan worden uitgevoerd. A[0] = A[0] + B[0]; for (i = 0; i < 100; i++) { B[i+1] = C[i] + D[i]; A[i+1] = A[i+1] + B[i+1]; } B[100] = C[99] + D[99];

Loop-Level Parallelism (4) Compilers kunnen dergelijke loop transformaties uitvoeren. - Via dependence analysis proberen zij de dependences in een loop in kaart te brengen. Problemen: pointers, indirect access, data die in verschillende functies wordt gebruikt. - Op basis hiervan kunnen bepaalde transformaties wel/niet worden uitgevoerd. True dependences moeten in tact blijven. Anti en output dependences kunnen worden verwijderd via renaming (vergelijk register renaming). Qua transformaties: denk aan loop (zo veel mogelijk) parallel maken, vectoriseren, loop interchange, loop blocking, enz.

Tot slot Een aantal jaren geleden al een groot verschil en dit verschil wordt alleen maar groter. SP DP Taken from Computer Architecture: A Quantitative Approach, fifth edition. Fig. 4.28

Tot slot (2) (Kon helaas geen recenter overzicht vinden.)

Tot slot: trends Het lijkt erop dat het aantal SIMD lanes groeit met dezelfde snelheid als het aantal cores op een chip groeit. Meer ideëen van vectorarchitecturen zullen hun weg vinden naar SIMD extensies. - We zien dit al met de toevoeging van gather in AVX2. Structuur GPU nog relatief eenvoudig, verwachting is dat hier nog ingewikkeldere/agressievere technieken gaan worden geïmplementeerd. - Daarnaast ook speciale functionaliteiten voor nieuwe toepassingen: e.g. deep learning.