Procesory kart graficznych i CUDA wer

Podobne dokumenty
Procesory kart graficznych i CUDA wer PR

Procesory kart graficznych i CUDA

GTX260 i CUDA wer

Programowanie kart graficznych

Procesory kart graficznych i CUDA wer

Obliczenia na GPU w technologii CUDA

Programowanie Współbieżne

Programowanie aplikacji równoległych i rozproszonych

Wprowadzenie do programowania w środowisku CUDA. Środowisko CUDA

Programowanie CUDA informacje praktycznie i. Wersja

Programowanie CUDA informacje praktycznie i przykłady. Wersja

Programowanie procesorów graficznych NVIDIA (rdzenie CUDA) Wykład nr 1

Porównanie wydajności CUDA i OpenCL na przykładzie równoległego algorytmu wyznaczania wartości funkcji celu dla problemu gniazdowego

Programowanie procesorów graficznych GPGPU

Przygotowanie kilku wersji kodu zgodnie z wymogami wersji zadania,

Programowanie PKG - informacje praktycznie i przykłady. Wersja z Opracował: Rafał Walkowiak

Programowanie procesorów graficznych GPGPU. Krzysztof Banaś Obliczenia równoległe 1

JCuda Czy Java i CUDA mogą się polubić? Konrad Szałkowski

Programowanie procesorów graficznych w CUDA.

Programowanie Równoległe wykład, CUDA, przykłady praktyczne 1. Maciej Matyka Instytut Fizyki Teoretycznej

CUDA obliczenia ogólnego przeznaczenia na mocno zrównoleglonym sprzęcie. W prezentacji wykorzystano materiały firmy NVIDIA (

Programowanie równoległe i rozproszone. Praca zbiorowa pod redakcją Andrzeja Karbowskiego i Ewy Niewiadomskiej-Szynkiewicz

Tesla. Architektura Fermi

Programowanie kart graficznych. Architektura i API część 1

Wprowadzenie do programowania w środowisku CUDA. Środowisko CUDA

i3: internet - infrastruktury - innowacje

Przetwarzanie Równoległe i Rozproszone

CUDA. cudniejsze przyk ady

Programowanie Równoległe Wykład, CUDA praktycznie 1. Maciej Matyka Instytut Fizyki Teoretycznej

CUDA. obliczenia na kartach graficznych. Łukasz Ligowski. 11 luty Łukasz Ligowski () CUDA 11 luty / 36

Procesory wielordzeniowe (multiprocessor on a chip) Krzysztof Banaś, Obliczenia wysokiej wydajności.

Programowanie kart graficznych

Programowanie Równoległe wykład 12. OpenGL + algorytm n ciał. Maciej Matyka Instytut Fizyki Teoretycznej

Programowanie współbieżne i rozproszone

Co to jest sterta? Sterta (ang. heap) to obszar pamięci udostępniany przez system operacyjny wszystkim działającym programom (procesom).

Wydajność systemów a organizacja pamięci. Krzysztof Banaś, Obliczenia wysokiej wydajności. 1

Zadania na zaliczenie przedmiotu Przetwarzanie równoległe Zebrał dla roku.ak. 2015/2016 Rafał Walkowiak,

Architektury komputerów Architektury i wydajność. Tomasz Dziubich

Wysokowydajna implementacja kodów nadmiarowych typu "erasure codes" z wykorzystaniem architektur wielordzeniowych

Dodatek A. CUDA. 1 Stosowany jest w tym kontekście skrót GPCPU (od ang. general-purpose computing on graphics processing units).

Ograniczenia efektywności systemu pamięci

Podstawy Informatyki Systemy sterowane przepływem argumentów

CUDA ćwiczenia praktyczne

16. Taksonomia Flynn'a.

Procesy i wątki. Krzysztof Banaś Obliczenia równoległe 1

Ograniczenia efektywności systemu pamięci

Budowa komputera Komputer computer computare

4. Procesy pojęcia podstawowe

Programowanie Rozproszone i Równoległe

Jacek Matulewski - Fizyk zajmujący się na co dzień optyką kwantową i układami nieuporządkowanymi na Wydziale Fizyki, Astronomii i Informatyki

Podstawy Informatyki DMA - Układ bezpośredniego dostępu do pamięci

Dr inż. Grażyna KRUPIŃSKA. D-10 pokój 227 WYKŁAD 7 WSTĘP DO INFORMATYKI

CUDA Median Filter filtr medianowy wykorzystujący bibliotekę CUDA sprawozdanie z projektu

Architektura mikroprocesorów TEO 2009/2010

Programowanie z wykorzystaniem technologii CUDA i OpenCL Wykład 1

Nowoczesne technologie przetwarzania informacji

Logiczny model komputera i działanie procesora. Część 1.

Literatura. 3/26/2018 Przetwarzanie równoległe - wstęp 1

Projektowanie. Projektowanie mikroprocesorów

4. Procesy pojęcia podstawowe

Literatura. 11/16/2016 Przetwarzanie równoległe - wstęp 1

Architektura komputerów

Tworzenie programów równoległych cd. Krzysztof Banaś Obliczenia równoległe 1

Procesor ma architekturę rejestrową L/S. Wskaż rozkazy spoza listy tego procesora. bgt Rx, Ry, offset nand Rx, Ry, A add Rx, #1, Rz store Rx, [Rz]

4 NVIDIA CUDA jako znakomita platforma do zrównoleglenia obliczeń

System obliczeniowy laboratorium oraz. mnożenia macierzy

Magistrala. Magistrala (ang. Bus) służy do przekazywania danych, adresów czy instrukcji sterujących w różne miejsca systemu komputerowego.

Zarządzanie pamięcią w systemie operacyjnym

Zapoznanie z technikami i narzędziami programistycznymi służącymi do tworzenia programów współbieżnych i obsługi współbieżności przez system.

5. Model komunikujących się procesów, komunikaty

Wskaźniki. Programowanie Proceduralne 1

Programowanie procesorów graficznych GPGPU

Przetwarzanie Równoległe i Rozproszone

Programowanie kart graficznych. Sprzęt i obliczenia

Tworzenie programów równoległych. Krzysztof Banaś Obliczenia równoległe 1

Architektura komputerów

Przykładem jest komputer z procesorem 4 rdzeniowym dostępny w laboratorium W skład projektu wchodzi:

Architektura potokowa RISC

Kompilator języka C na procesor 8051 RC51 implementacja

Stronicowanie w systemie pamięci wirtualnej

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Systemy wbudowane. Uproszczone metody kosyntezy. Wykład 11: Metody kosyntezy systemów wbudowanych

Moc płynąca z kart graficznych

Projektowanie algorytmów równoległych. Zbigniew Koza Wrocław 2012

Budowa i zasada działania komputera. dr Artur Bartoszewski

Programowanie kart graficznych. Architektura i API część 2

Programowanie w języku C++

10/14/2013 Przetwarzanie równoległe - wstęp 1. Zakres przedmiotu

CUDA część 1. platforma GPGPU w obliczeniach naukowych. Maciej Matyka

Wydajność systemów a organizacja pamięci, czyli dlaczego jednak nie jest aż tak źle. Krzysztof Banaś, Obliczenia wysokiej wydajności.

Tworzenie programów równoległych. Krzysztof Banaś Obliczenia równoległe 1

4. Procesy pojęcia podstawowe

MOŻLIWOŚCI PROGRAMOWE MIKROPROCESORÓW

Programowanie w modelu równoległości danych oraz dzielonej globalnej pamięci wspólnej. Krzysztof Banaś Obliczenia równoległe 1

Procesory wielordzeniowe (multiprocessor on a chip) Krzysztof Banaś, Obliczenia wysokiej wydajności.

PROGRAMOWANIE WSPÓŁCZESNYCH ARCHITEKTUR KOMPUTEROWYCH DR INŻ. KRZYSZTOF ROJEK

Programowanie współbieżne Wykład 7. Iwona Kochaoska

Zaawansowane programowanie w C++ (PCP)

Czyń CUDA (część 1) Powinieneś wiedzieć: Od czytelnika wymagana jest znajomość C++ oraz podstawowych zasad programowania równoległego.

Lab 9 Podstawy Programowania

Transkrypt:

wer 1.4 18.04.2016 Litreratura: CUDA textbook by David Kirk from NVIDIA and Prof. Wen-mei Hwu from UIUC. CUDA w przykładach. Wprowadzenie do ogólnego programowania procesorów GP, J.Sanders, E.Kandrot, Helion Getting Started with CUDA, Greg Ruetsch, Brent Oster, NVIDIA Technical Brief NVIDIA GeForce GTX 200 GPU Architectural Overview 1

Motywacje: Problemy postępu technologii procesorów sytuacja 10 lat temu Problemy: Energia - tania, tranzystory drogie Obliczenia - wolne, dostęp do pamięci - wolny, Rozwiązania: wzrost prędkości obliczeń uzyskiwany dzięki współbieżności przetwarzania na poziomie instrukcji realizacja analiza kodu przez kompilatory, dynamiczna kolejność przetwarzania instrukcji, przetwarzanie spekulatywne, zastosowanie pamięci podręcznej procesora. 2

Motywacje: Problemy postępu technologii procesorów sytuacja obecnie Problemy: Przeszkoda energetyczna energia - droga, tranzystory tanie Przeszkoda pamięci : obliczenia - szybkie, dostęp do pamięci - wolny, (np. 200 cykli - dostęp do DRAM, 4 cykle - mnożenie FP) Rozwiązanie wzrost efektywności poprzez: współbieżność wątków - powszechna równoległość wieloprocesorowa i wielordzeniowa ogranicza zużycie mocy i równoległość danych - jednakowe operacje na wielu jednostkach danych proste procesory SIMD, GPU łączone dostępy do pamięci i przełączanie wątków. 3

Zasady ogólne: Compute Unified Device Architecture (NVIDIA) - CUDA Sposób na programowanie PKG (GPU, karty graficzne): model programowania i środowisko dla programowania równoległego CUDA zawiera: specyfikację architektury sprzętu, język programowania, interfejs języka dla aplikacji czyli API runtime API lub device API. 4

Zasady ogólne: Cechy CUDA Dostęp wątków do pamięci: wątek może realizować odczyt dowolnej lokacji pamięci globalnej karty, wątek może czytać/zapisywać potrzebną liczbę lokacji pamięci globalnej karty, wątki mogą współdzielić dane w pamięci współdzielonej. Niski nakład pracy wejścia niezbędny dla poznania CUDA: niewielkie rozszerzenie języka C, brak wymagań na znajomość zagadnień graficznych. Umożliwia wykorzystanie systemów niejednorodnych - CPU + karta graficzna (GPU) o rozdzielonych pamięciach. (notacja: CPU -host, GPU device) 5

Zasady ogólne: Współpraca wątków Znaczenie współpracy: współdzielenie wyników brak konieczności wielokrotnych obliczeń korzystanie ze współdzielonej pamięci pozwala na: obniżenie wymagań na przepustowość pamięci głównej możliwość efektywnej współpracy (pamięć współdzielona, synchronizacja) w ramach mniejszych grup wątków blokach wątków Ograniczenie możliwości współpracy w ramach dowolnie dużej grupy wątków (limit na wielkość bloku wątków) często na danym etapie obliczeń dla problemu każdy blok wątków realizuje niezależne obliczenia(na tych samych lub innych procesorach, w tym samym lub innym czasie). 6

Krótka legenda: Przetwarzanie w modelu CUDA Multiprocesor (SM) fragment struktury przetwarzającej - składa się z wielu rdzeni, jednostek przetwarzających specjalnego przeznaczenia i pamięci współdzielonej. Warp osnowa - logiczna grupa 32 jednostek wykonawczych multiprocesora realizujących tę samą instrukcję dla wiązki wątków. Kernel funkcja kod realizowanych przez PKG (brak współbieżności kerneli, nowsze karty możliwa). Grid grupa (struktura) wątków realizująca kernel (struktura logiczna max 2 (3) wymiarowa). Blok wątków grupa wątków - część gridu (max 3 wymiarowy) blok jest przetwarzany na jednym multiprocesorze, blok dzieli się na wiązki Wiązka wątków grupa wątków (max 32) część kolejnych (wierszami ) wątków bloku, przetwarzana jednocześnie, wątki wiązki wykonują ten sam rozkaz (część watków może rozkazu nie wykonywać warunek w kodzie). 7

Przetwarzanie w modelu CUDA Wywołanie w kodzie dla procesora komputera funkcji kernela umożliwia uruchonienie gridu składającego się z wielu bloków wątków. Wątki tego samego bloku realizowane na tym samym SM: współpracują przez pamięć współdzieloną, mogą się efektywnie synchronizować. Przetwarzanie bloków wątków jest przenośne i skalowalne przetwarzanie można realizować na różnych kartach scharakteryzowanych wymaganą zgodnością obliczeniową compute capability. 8

CPU - GPU filozofie architektur (1) Przetwarzanie GPU jest skoncentrowane na obliczeniach i przepustowości, stosowana metodologia: przerwanie przetwarzania grupy wątków na czas oczekiwania na dane, realizacja obliczeń na rzecz innej grupy wątków. Przetwarzanie CPU jest zorientowane na redukcję opóźnienia i zapełnienie potoków przetwarzania, stosowana metodologia: dążenie do wysokich współczynników trafień i efektywnej predykcji rozgałęzień kodu, dynamiczna zmiana kolejności instrukcji. 9

GPU filozofia architektury (2) Stopień wykorzystania struktur logicznych przez jednostki funkcjonalne CPU i GPU. W GPU znacznie więcej - niż w CPU - tranzystorów jest wykorzystywanych do implementacji ALU, niż do sterowania przetwarzaniem i pamięci podręcznej. Efekt: wymaganie na większą niż w CPU przewidywalność w dostępie do danych i przepływie sterowania dla programów efektywnych w GPU. 10

Równoległość zadań a równoległość danych Równoległość zadań niezależne procesy realizują dowolne zadania z niewielką ilością komunikacji Łatwa do implementacji: wspólczesne systemy operacyjne w systemach wieloprocesorowych + OpenMP Równoległość danych wiele jednostek danych na których realizowane mają być te same obliczenia, możliwość wykorzystania wielu jednostek przetwarzających lecz: konieczność przeprojektowania tradycyjnych algorytmów. Implementacja efektywna w systemach kart graficznych 11

GPU - filozofia architektury (4) CPU szybkie pamięci podręczne (nadają się do algorytmów z ponownym wykorzystaniem danych) wiele różnych procesów/wątków wysoka efektywność przetwarzania pojedynczego wątku (warunek - lokalność dostępów) GPU - PKG wiele jednostek wykonawczych, efektywny (przepustowość!, opóźnienie?) dostęp do pamięci urządzenia, realizacja tego samego kodu na wielu elementach danych, wysoka przepustowość dla wielu obliczeń równoległych (warunek jednakowe operacje dla wiązki wątków) Zatem: CPU właściwe dla równoległości zadań GPU właściwe dla równoległości danych 12

Compute Capability 5.0 na podstawie karty GTX745 Sprzęt używany na laboratorium lab 2.6.22 Architektura Maxwell (GTX745 1,033GHz): posiada multiprocesory Maxwell SM SMM SMM zawiera 128 rdzenii (operacje arytmetyczne FP) i 32 SFU (f. wykładnicza, logarytm, pierwiastek). Układ scalony GM107 - posiada 5 SMM multipocesorów jeden GPC Graphics Proseccing Cluster. W karcie GTX 745 (lab 2.6.22) 3 SMM są uaktywnione 384 rdzeni Posiada: Compute capability 5.0 Pamięć podręczna danych i dynamiczna równoległość Inne układy scalone serii Maxwell to GM108, GM204 (CC5.2) Prędkość obliczeń (pojedyńczej precyzji) 2 operacje (+*) wykonuje na rdzeń i na cykl (podwójna precyzja 1/32) czyli ok. 2*400 GFlops 13

Sprzęt używany na laboratorium lab 2.6.22 Compute capability dla GTX745 - Maxwell to CC 5.0: wątków na blok - Max 1024 wielkość WARP - 32 liczba bloków na SMM max 32 wiązki (ang. WARP) rezydujące na SMM max 64 (2048 wątków) 32 bit rejestry na SMM - 64 K 32 bit rejestry na wątek 255 SMEM na SMM 64 KB Banki SMEM 32 14

Szeregowanie przetwarzania CC 5.0 1. Poszczególne bloki wątków są rozdzielane do przetwarzania na SM, potencjalnie więcej niż jeden blok, lecz <= 32 bloki (równocześnie) dla Compute Capability 5.0 2. SM (CC 5.0) realizuje jednoczesne obliczenia dla wiązek, których liczba jest ograniczona liczbą warpów utworzonych z jednostek wykonawczych w SM: 128 ALU i 32 SFU, pozostałe wiązki oczekują na swoją kolej (dostępne warpy) lub dane. SM przetwarza wiązki przydzielonych bloków do końca. 3. Zwolnienie zasobów SM przydzielonych do bloku rejestry, pamięć - następuje po zakończeniu przetwarzania bloku daje możliwość przetwarzania kolejnego bloku. 15

Szeregowanie wątków w ramach bloków wątków i jednostki warp w SM Przykładowa kolejność dotyczy przetwarzania dla jednego warpa kolejno przetwarzane: Wiązka1 bloku 1, Wiązka 1 bloku 2, Wiązka 1 bloku 3, Wiązka 2 bloku 3 TB1, W1 stall okres utknięcia wiązki W1 bloku B1, ze względu na brak danych do obliczeń. 16

Kernel jest realizowany przez grid - tablicę wątków: wszystkie watki otrzymują ten sam kod każdy watek posiada unikalny w gridzie identyfikator (zależy od blockidx.x, blockdim.x, threadidx.x) używany do określenia pracy: np. obliczenia wykorzystywanego adresu pamięci i sterowania przebiegiem obliczeń Wątki i ich identyfikatory - threadid 1 2 4 5 3 6 7 8 float x = input[threadid]; Przykład kodu kernela: float y = func(x); output[threadid] = y; 17

Model pamięci dla PKG CUDA Możliwe dostępy do pamięci w ramach kodu: Kernel (wątki dla PKG) R/W rejestru w ramach wątku (lokalnie szybki dostęp) R/W pamięci prywatnej wątku (w pamięci globalnej karty powolny dostęp) R/W pamięci współdzielonej w ramach bloku wątków (szybki dostęp) R/W pamięci globalnej w ramach gridu (w pamięci globalnej karty powolny dostęp) odczyt pamięci wartości stałych (constant) w ramach gridu Kod komputera dostępowego (host) R/W pamięci gridu globalnej i pamięci stałych 18

Struktura pamięci systemu CPU-GPU Kod CPU zarządza pamięcią GPU - alokacja, zwolnienie, kopiowanie danych pomiędzy pamięciami: host do device oraz device do host. 19

Wywołanie kernela - parametry konfiguracyjne 1. Zmodyfikowana składnia wywołania funkcji dla PKG (CUDA): nazwa_funkcji <<<dim3 opis_gridu, dim3 opis_bloku>>> (parametry_kernela); 2. Konfiguracja uruchomienia określona jest poprzez <<< >>> 3. opis_gridu oznacza: liczbę wymiarów i wielkość gridu (tj. rozmiary) podane w jednostkach bloku, max 2(3) wymiary x, y, z liczba bloków uruchomionych w grid wynosi opis_gridu.x * opis_gridu.y 4. opis_bloku oznacza: liczbę wymiarów i wielkość bloku (tj. rozmiary) w wątkach, max 3 wymiary bloków x,y,z, liczba wątków na blok wynosi zatem opis_bloku.x * opis_bloku.y * opis_bloku.z Nie określone wartości typu dim3 zostają automatycznie zainicjowane do wartości 1. 5. Kompilator zamienia to wywołanie w blok kodu, który zostaje skonfigurowany (ustalona struktura i liczba wątków) i zostanie uruchomiony asynchronicznie na PKG. 20

Zmienne automatyczne konfiguracji wątek dowiaduje się swojwgo ID i określa pracę Wszystkie funkcje global i device mają dostęp do automatycznie zdefiniowanych zmiennych o następujących nazwach i typie : dim3 griddim; // ile bloków w wymiarze griddim.x, griddim.y dim3 blockdim; // ile wątków w wymiarze blockdim.x... dim3 blockidx; //który blok blockidx.x <= griddim.x-1 dim3 threadidx; //który wątek threadidx.x <= blockdim.x-1 Nie można przyporządkowywać wartości zmiennych automatycznych i pobierać adresu, wykorzystywane są np. do adresowania pamięci i określania pracy wątku. 21

Inkrementacja tablicy porównanie kodu CPU-GPU program CPU void inc_cpu(int *a, int N) { } int idx; for (idx = 0; idx<n; idx++) a[idx] = a[idx] + 1; int main() { } inc_cpu(a, N); program CUDA global void inc_gpu(int *a, int N) { int idx = blockidx.x * blockdim.x + threadidx.x; if (idx < N) a[idx] = a[idx] + 1; //grid i blok jednowymiarowe } int main() { dim3 dimblock (blocksize); dim3 dimgrid( ceil( N / (float)blocksize) ); inc_gpu<<<dimgrid, dimblock>>>(a, N); } // sufit dla uzyskania wystarczającej liczby wątków 22

Określniki rodzaju zmiennych (kernel) device Zmienne przechowywane w pamięci globalnej (duża pamięć, długi czas dostępu, (brak pp w starszych kartach), alokowana przez cudamalloc, dostępna dla wszystkich wątków, przez czas życia aplikacji. shared Zmienne przechowywane w pamięci współdzielonej SM (szybki czas dostępu), dostępne przez wątki tego samego bloku, dostępne w czasie istnienia bloku, jedna kopia obiektu na blok wątków, rozmiar specyfikowany przy kompilacji lub w konfiguracji uruchomienia, UWAGA: synchronizacja jest niezbędna do uzyskania obrazu wykonanych operacji również w ramach innych wątków bloku (lub deklaracja volatile), dane _shared_ są niedostępne z CPU. 23

Określniki rodzaju zmiennych (kernel) constant Globalne zmienne przechowywane w pamięci GPU, dla GPU możliwy odczyt, dla CPU API odczyt/zapis bez określnika rodzaju Zmienne lokalne wątku (typy skalarne i wbudowane typy wektorowe) przechowywane w rejestrach lub (gdy się nie mieszczą ) w pamieci globalnej naywane local memory. 24

Optymalizacja dostępu do pamięci Pamięć globalna: Dostęp do pamięci globalnej grupy wątków realizowanych jednocześnie WARP (1/2 WARP) może być zrealizowany jako jedna transakcja z pamięcią (połączone - coalesced od koalicja) Coalesced vs. Non-coalesced => różnica rzędu w wielkości czas dostępu dotyczy dostępów do pamięci globalnej i lokalnej GPU Pamięć współdzielona: Unikanie konfliktów dostępu do tych samych banków w pamięci współdzielonej (cel: sąsiednie wątki WARP odwołują się do różnych adresów modulo liczba banków pamięci brak konfliktów) W CC 5.0 odwołania do kolejnych 32 bitowych słów trafiają do różnych 32 banków pamięci. 25

Efektywność przetwarzania możliwe sytuacje 1. Przepustowość dostępu do pamięci za mała obniżenie efektywności obliczeń ze względu na brak danych. 2. Przepustowość dostępu do pamięci wystarczająca obniżenie efektywności obliczeń ze względu na brak danych powodowany opóźnieniem dostępu (czas odpowiedzi) 3. Przepustowość dostępu do pamięci wystarczająca wysoka efektywności obliczeń ze względu na wystarczającą liczbę warpów, które posiadają dane gotowe do obliczeń. Liczba wątków (równocześnie na SM) niezbędnych do efektywnego przetwarzania zależna od CGMA parametr ten określa jak długo zajmujemy procesor pobranymi z pamięci globalnej danymi. 26

Łączenie dostępów dla CC 5.0 Dane pobierane z pamięci globalnej są buforowane w pamieci podręcznej L2 wspólnej dla wszystkich SM. Żądania z WARP są odwzorowane na linie pamięci podręcznej L2 (32 bajty) i zaspokajane z pamięci podręcznej (transakcje 32 bajtowe) lub globalnej transakcje 128 bajtowe. 27

Zalety pamięci współdzielonej bloku wątków Sto razy szybszy czas dostępu do pamięci współdzielonej niż czasu dostępu do pamięci globalnej. Możliwość współpracy wątków bloku. Użycie grupy wątków do załadowania danych i obliczenia na danych współdzielonych przez wszystkie wątki. Użycie do zapobieżenia dostępom niepołączonym Etapy pobrań i zapisu przy użyciu pamięci współdzielonej dla uporządkowania adresowania dostępów nie dających się (wg algorytmu) połączyć. 28

Synchronizacja przetwarzania bloku wątków w SM void syncthreads(); synchronizacja wątków bloku, wprowadza barierę dla wątków bloku, używana do zapobiegnięcia wyścigowi w dostępie do pamięci współdzielonej multiprocesora musi wystąpić w wykonywanym kodzie wszystkich wątków bloku. 29

Synchronizacja przetwarzania CPU GPU Wszystkie uruchomienia funkcji kernel są asynchroniczne: sterowanie wraca natychmiast do kodu CPU, możliwe są równoczesne obliczenia CPU i GPU funkcja kernel jest realizowana po zakończeniu wcześniejszych wywołań CUDA. cudamemcpy(); funkcja jest synchroniczna, sterowanie wraca do kodu CPU po jej zakończeniu, kopiowanie jest realizowane po zakończeniu wszystkich wcześniejszych (ten sam strumień) wywołań CUDA. cudathreadsynchronize() ; przerywa przetwarzanie kodu CPU do momentu zakończenia wcześniejszych wywołań CUDA 30

Równoczesność transmisji danych (HOST DEVICE) i obliczeń (GPU, CPU) Wywołania asynchroniczne funkcji API i strumienie pozwalają na nakładanie się komunikacji i obliczeń Obliczenia CPU mogą się nakładać z transferem danych na wszystkich typach GPU (transfer asynchroniczny) Obliczenia GPU mogą się nakładać z transferem danych na kartach z Concurrent copy and execution (od compute capability >= 1.1) - realizacja w różnych strumieniach. Strumień (Stream) = sekwencja operacji realizowana na GPU Operacje z różnych strumieni mogą być realizowane równocześnie. Identyfikator strumienia jest używany jako argument do wywołań asynchronicznych i uruchomień funkcji kernel. 31

Asynchroniczna komunikacja host-device Asynchroniczne transfery host-device zwracają sterowanie natychmiast do CPU cudamemcpyasync(dst, src, size, dir, stream); wymagają pamięci o stałej lokacji (bez wirtualizacji) (alokowanej za pomocą cudamallochost), równoczesność obliczeń CPU i przesyłu danych, wzrost efektywności komunikacji poprzez wykorzystanie wprost pamięci o stałej lokacji. Przykład: cudamemcpyasync(a_d, a_h, size, cudamemcpyhosttodevice, 0); kernel<<<grid, block>>>(a_d); obliczenia_na_cpu(); cudathreadsynchronize(); //oczekiwanie na zakończenie przetwarzania GPU Uwaga: 0 oznacza strumień zerowy ten sam w którym niejawnie (domyślnie) uruchamiany jest kernel 32

Zrównoleglenie przetwarzania funkcji kernel i transferu danych HOST-GPU Wymagany jest własność Concurrent copy and execute pola deviceoverlap zmiennej cudadeviceprop. Kernel i funkcja transferu używać muszą różnych niezerowych strumieni. Wywołanie funkcji CUDA dla strumienia 0 blokuje przetwarzanie tej funkcji do momentu zakończenia wszystkich wcześniejszych wywołań (wszystkich strumieni) - nie zezwala na zrównoleglenie realizacji wywołań. Przykład: cudastreamcreate(&stream1); cudastreamcreate(&stream2); cudamemcpyasync(a_d, a_h, size, cudamemcpyhosttodevice, stream1); kernel<<<grid, block, 0, stream2>>>(inne_niz_a_d_dane); UWAGA: aby ten sam wątek mógł wywołać kernel, transfer musi być asynchroniczny. 33

Przykład: wieloetapowa komunikacja równoległa z przetwarzaniem GPU (i CPU) for (i=0; i<nstreams; i++) { } offset= oblicz_offset(); cudamemcpyasync(a_d+offset, a_h+offset, size, dir, stream[i]); kernel<<<nblocks, nthreads, 0, stream[i]>>>(a_d+offset); czas Rysunek przedstawia przebieg Sekwencyjnego i równoległego transfer danych (CPU_GPU) i przetwarzania na GPU. 34

Synchronizacja GPU/CPU Wywołania związane ze strumieniem i ze zdarzeniami: zdarzenia można wprowadzić do strumienia : cudaeventrecord(event, stream) zdarzenie jest zarejestrowane, gdy GPU dotrze do niego (w przetwarzanym strumieniu) zdarzenie zarejestrowane = przypisana wartość etykiety czasowej (GPU clocktick), użyteczne dla pomiaru czasu cudaeventsynchronize(event) blokada wątku CPU do momentu zarejestrowania zdarzenia cudaeventquery(event) bada czy zdarzenie jest zarejestrowane zwraca cudasuccess, cudaerrornotready nie blokuje przetwarzania wątku CPU 35

Synchronizacja GPU/CPU Dotyczy bieżącego kontekstu wywołania: cudathreadsynchronize() blokuje CPU do zakończenia wszystkich wcześniejszych wywołań CUDA z CPU Związane ze strumieniem: cudastreamsynchronize(stream) blokuje CPU do zakończenia wszystkich wywołań CUDA dla danego strumienia - parametru cudastreamquery(stream) bada czy strumień jest pusty zwraca cudasuccess, cudaerrornotready,... nie blokuje wątku CPU 36

Podstawowe operacje na pamięci GPU Alokacja pamięci : cudamalloc(void ** pointer, size_t nbytes) Wypełnienie pamięci: cudamemset(void * pointer, int value, size_t count) Oddanie pamięci: cudafree(void* pointer) Przykładowy kod: int n = 1024; int nbytes = 1024*sizeof(int); int *a_d = 0; cudamalloc( (void**)&a_d, nbytes ); cudamemset( a_d, 0, nbytes); cudafree(a_d); 37

Kopiowanie daych CPU - GPU cudamemcpy(void *dst, void *src, size_t nbytes, cudamemcpykind direction); zmienna direction określa kierunek transferu danych enum cudamemcpykind - wartości w tym typie to: cudamemcpyhosttodevice cudamemcpydevicetohost cudamemcpydevicetodevice Funkcja ta blokuje przetwarzanie na CPU, kończy się po zakończeniu przesłania. Kopiowanie rozpoczyna się typowo po zakończeniu poprzedniego wywołania CUDA. 38

Przykład kodu dla transferu danych kierunki przesłań zgodnie z rysunkiem int main(void) { float *a_h, *b_h; // host data float *a_d, *b_d; // device data int N = 14, nbytes, i ; nbytes = N*sizeof(float); a_h = (float *)malloc(nbytes); b_h = (float *)malloc(nbytes); cudamalloc((void **) &a_d, nbytes); cudamalloc((void **) &b_d, nbytes); for (i=0, i<n; i++) a_h[i] = 100.f + i; cudamemcpy(a_d, a_h, nbytes, cudamemcpyhosttodevice); cudamemcpy(b_d, a_d, nbytes, cudamemcpydevicetodevice); cudamemcpy(b_h, b_d, nbytes, cudamemcpydevicetohost); for (i=0; i< N; i++) assert( a_h[i] == b_h[i] ); free(a_h); free(b_h); cudafree(a_d); cudafree(b_d); } return 0; Host a_h Device a_d b_h b_d 39

Zasady optymalizacji algorytmu dla GPU 1. Algorytm oparty na niezależnej równoległości przetwarzania. 2. Maksymalizacja intensywności obliczeń arytmetycznych - miara współczynik CGMA (compute to global memory access ratio). Czasem lepiej ponownie obliczyć niż pobrać z pamięci, gdyż GPU dostarcza użytkownikowi przede wszystkim wiele ALU, a nie szybkiej pamięci. 3. Unikać kosztownych transferów do host. 4. Minimalizacja użycia zasobów przez wątek dla umożliwienia wielu blokom wątków aktywności w ramach SM. Zapewnienie wystarczającej ilości pracy SM poprzez dużą liczbę wątków i dużą liczbę bloków wątków (maksymalizacja równoległości). 5. Optymalizacja dostępów (inna niż CPU!) do pamięci dla wykorzystania maksymalnej przepustowości pamięci. 6. Optymalizacja wykorzystania instrukcji kodu dla maksymalizacji prędkości obliczeń (np. rozwijanie pętli usuwanie instrukcji sterujących). 40

Operacje atomowe w pamięci GPU Compute capability >=1.1 Operacje add, sub, increment, decrement, min, max,... and, or, xor exchange, compare, swap 1. Operacje atomowe na 32-bit słowach pamięci globalnej wymagają compute capability >= 1.1 (G84/G86/ G92) 2. Operacje atomowe na 32-bit słowach pamięci współdzielonej i 64-bit słowach pamięci globalnej wymagają compute capability >= 1.2 41

Kwalifikatory funkcji CUDA Kernel określony za pomocą: global Funkcja wywoływana w kodzie host i wykonywana w device, musi: zwracać void, posiadać stałą liczbę argumentów argumenty automatycznie kopiowane z CPU do GPU nie może: być rekursywna i odwoływać się do pamięci CPU Inne kwalifikatory: device Funkcja wywoływana w kodzie device i wykonywana w device. host Funkcja wywoływana i realizowana na host Można używać host i device równocześnie. 42

Wywołanie kernela - przykłady dim3 grid, block; grid.x = 2; grid.y = 4; block.x = 8; block.y = 16; nazwa_kernela<<<grid, block>>>(...); dim3 grid(2, 4), block(8,16); // to samo za pomocą funkcji tworzącej nazwa_kernela<<<grid, block>>>(...); // 8*128=1024 wątki nazwa_kernela<<<32,512>>>(...); // 1 wymiarowy grid - 32 bloki, jednowymiarowy blok wątków po 512 wątków 43

Zmienne automatyczne konfiguracji przykłady Dla jednowymiarowego gridu i bloku o parametrach: blockidx.x, blockdim.x, threadidx.x globalny identyfikator wątku wyliczony wg wzoru: blockidx.x*blockdim.x + threadidx.x Ogólnie liczba wątków dowolnego gridu: griddim.x *griddim.y*blockdim.x*blockdim.y*blockdim.z 44

Użycie pamięci współdzielonej Rozmiar znany podczas kompilacji Rozmiar znany przy wywołaniu global void kernel( ) { shared float sdata[256]; } int main(void) { kernel<<<nblocks,blocksize>>>( ); } global void kernel( ) { extern shared float sdata[]; } int main(void) { int smbytes = blocksize*sizeof(float); kernel<<<nblocks, blocksize, smbytes>>>( ); } 45

Materiały Nvidia http://docs.nvidia.com/cuda/pdf/cuda_c_programming_guide.pdf http://docs.nvidia.com/cuda/pdf/cuda_c_best_practices_guide.pdf http://docs.nvidia.com/cuda/pdf/maxwell_tuning_guide.pdf 46

Znaczenie optymalizacji wykorzystania zasobów multiprocesora (SM) Wielkość wykorzystanych przez kernel rejestrów, pamięci lokalnej, współdzielonej i stałych można poznać za pomocą programu NVIDIA profiler oraz podczas kompilacji za pomocą opcji linii wywołania kompilatora nvcc --ptxas-options=-v Liczba rejestrów używanych przez kernel może mieć duży wpływ na liczbę bloków rezydujących na multiprocesorze. Przykład: CC 1.3 16k 32 bitowych rejestów w SM kernel wymaga - 16 rejestrów dla każdego wątku, Blok 512 wątków, można przydzielić 2 bloki które 2*512*16 wyczerpią wszystkie dostępne rejestry. wzrost zapotrzebowania na liczbę rejestrów o 1 na wątek zmniejsza liczbę przydzielonych bloków do SM o jeden, a przydzielonych warp o połowę!! (z 32 do 16). 47