Programowanie kart graficznych

Podobne dokumenty
Wprowadzenie do programowania w środowisku CUDA. Środowisko CUDA

Programowanie Współbieżne

Programowanie kart graficznych

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

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

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

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

Wprowadzenie do programowania w środowisku CUDA. Środowisko CUDA

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

i3: internet - infrastruktury - innowacje

Tesla. Architektura Fermi

Programowanie kart graficznych. Sprzęt i obliczenia

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

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

Programowanie w języku C++ Grażyna Koba

Programowanie z wykorzystaniem technologii CUDA i OpenCL Wykład 1

Przetwarzanie Równoległe i Rozproszone

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

Programowanie aplikacji równoległych i rozproszonych

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

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 (

Algorytmy dla maszyny PRAM

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

Zaawansowane programowanie w języku C++ Zarządzanie pamięcią w C++

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

Moc płynąca z kart graficznych

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

Przygotowanie kilku wersji kodu zgodnie z wymogami wersji zadania,

Programowanie Strukturalne i Obiektowe Słownik podstawowych pojęć 1 z 5 Opracował Jan T. Biernat

Algorytmy i Struktury Danych

Budowa komputera. Magistrala. Procesor Pamięć Układy I/O

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

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

Podstawy programowania. Wykład: 7. Funkcje Przekazywanie argumentów do funkcji. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

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

Podstawy programowania. Wykład 6 Wskaźniki. Krzysztof Banaś Podstawy programowania 1

Budowa i zasada działania komputera. dr Artur Bartoszewski

Programowanie CUDA informacje praktycznie i. Wersja

Przetwarzanie Równoległe i Rozproszone

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

Zastosowanie technologii nvidia CUDA do zrównoleglenia algorytmu genetycznego dla problemu komiwojażera

4. Procesy pojęcia podstawowe

Budowa komputera. Magistrala. Procesor Pamięć Układy I/O

Architektura Systemów Komputerowych. Rozwój architektury komputerów klasy PC

Programowanie strukturalne i obiektowe. Funkcje

ZARZĄDZANIE PAMIĘCIĄ W TECHNOLOGII CUDA

Algorytm. a programowanie -

Sprzęt komputerowy 2. Autor prezentacji: 1 prof. dr hab. Maria Hilczer

Budowa komputera Komputer computer computare

Budowa Mikrokomputera

Programowanie sterowników przemysłowych / Jerzy Kasprzyk. wyd. 2 1 dodr. (PWN). Warszawa, Spis treści

UKŁADY MIKROPROGRAMOWALNE

Zarządzanie pamięcią operacyjną

4. Procesy pojęcia podstawowe

Praca dyplomowa magisterska

Programowanie procesorów graficznych w CUDA.

Redukcja czasu wykonania algorytmu Cannego dzięki zastosowaniu połączenia OpenMP z technologią NVIDIA CUDA

Obliczenia na GPU w technologii CUDA

JAVA. Java jest wszechstronnym językiem programowania, zorientowanym. apletów oraz samodzielnych aplikacji.

RDZEŃ x86 x86 rodzina architektur (modeli programowych) procesorów firmy Intel, należących do kategorii CISC, stosowana w komputerach PC,

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

Alternatywne modele programowania równoległego

Libra.cs.put.poznan.pl/mailman/listinfo/skisrkolo.

Wstęp do obliczeń równoległych na GPU

Język programowania PASCAL

INFORMATYKA, TECHNOLOGIA INFORMACYJNA ORAZ INFORMATYKA W LOGISTYCE

Wstęp do programowania 2

16. Taksonomia Flynn'a.

Sprzęt komputerowy 2. Autor prezentacji: 1 prof. dr hab. Maria Hilczer

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

Architektura von Neumanna

Podstawy Informatyki Systemy sterowane przepływem argumentów

ZASADY PROGRAMOWANIA KOMPUTERÓW

Akceleracja obliczeń algebry liniowej z wykorzystaniem masywnie równoległych, wielordzeniowych procesorów GPU Świerczewski Ł.

4 Literatura. c Dr inż. Ignacy Pardyka (Inf.UJK) ASK MP.01 Rok akad. 2011/ / 24

Programowanie w języku Python. Grażyna Koba

Zarządzanie pamięcią operacyjną

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

dr inż. Konrad Sobolewski Politechnika Warszawska Informatyka 1

Architektura komputerów

UTK ARCHITEKTURA PROCESORÓW 80386/ Budowa procesora Struktura wewnętrzna logiczna procesora 80386

Architektura komputerów

Podsystem graficzny. W skład podsystemu graficznego wchodzą: karta graficzna monitor

Analiza ilościowa w przetwarzaniu równoległym

Księgarnia PWN: Włodzimierz Stanisławski, Damian Raczyński - Programowanie systemowe mikroprocesorów rodziny x86

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

1 Podstawy c++ w pigułce.

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

Laboratorium nr 12. Temat: Struktury, klasy. Zakres laboratorium:

Rekurencja (rekursja)

Wykorzystanie architektury Intel MIC w obliczeniach typu stencil

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

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

1 Wątki 1. 2 Tworzenie wątków 1. 3 Synchronizacja 3. 4 Dodatki 3. 5 Algorytmy sortowania 4

Technika mikroprocesorowa. Struktura programu użytkownika w systemie mikroprocesorowym

Architektura komputerów

Podstawy programowania komputerów

Transkrypt:

Programowanie kart graficznych Sławomir Wernikowski swernikowski@wi.zut.edu.pl

Wykład #1: Łagodne wprowadzenie do programowania w technologii NVIDIA CUDA

Terminologia: Co to jest GPGPU? General-Purpose computing on a Graphics Processing Unit wykorzystanie sprzętu graficznego (specjalizowanego) do niegraficznych obliczeń (ogólnego przeznaczenia)

Terminologia: Co to jest CUDA? Compute Unified Device Architecture architektura sprzętowo-programowa ukierunkowana na przetwarzanie typu data parallel

Krótki rys historyczny: 2006: Pierwsze implementacje pod postacią kart graficznych PCI-E z zabudowanymi dedykowanymi układami VLSI GeForce 8

Krótki rys historyczny: 2006: Kolejne implementacje pod postacią kart pozbawionych części generującej sygnał wizyjny NVIDIA Tesla Personal Supercomputer (Dell, Lenovo)

Krótki rys historyczny: CC = Compute Capability: 1.0 wczesne konstrukcje architektury CUDA, implementowane przez układy GPU serii 8800; dla przykładu, maksymalna liczba równolegle pracujących wątków jest tu równa 768, a każdy z multiprocesorów dysponuje 8192 rejestrami o szerokości 32 bitów

Krótki rys historyczny: CC: 1.1 implementowane w układach GPU serii 1x0; od 1.0 odróżnia się możliwością kodowania funkcji stałoprzecinkowych operujących na danych o szerokości 32 bitów, przechowywanych w pamięci urządzenia

Krótki rys historyczny: CC: 1.2 powiązane z układami GPU serii GT 2x0; maksymalna liczba jednocześnie uruchomionych wątków jest tu równa 1024, a liczba rejestrów dostępnych dla multiprocesorów wynosi 16384

Krótki rys historyczny: CC: 1.3 wersja rozwojowa w stosunku do CC 1.2; jako pierwsza wprowadziła do architektury CUDA arytmometr zmiennoprzecinkowy dla danych podwójnej precyzji; implementowana w układach serii GTX 2x0

Krótki rys historyczny: CC: 2.0 implementowana w układach serii 4x0; maksymalna liczba wątków to 1536 przy liczbie dostępnych rejestrów równej 32768

Krótki rys historyczny: CC: 3.0 maksymalna liczba wątków: 2048

Krótka charakterystyka

Rdzeń jednostka przetwarzająca zawiera pewną liczbę procesorów, określanych w tej technologii mianem rdzeni (ang. cores) liczba rdzeni zmienia się w różnych wykonaniach kart CUDA w zależności od pożądanych cech urządzenia i docelowej grupy przyszłych użytkowników oraz aktualnego zaawansowania technologii wczesne karty serii 8800GS zawierały 64 rdzenie, urządzenia serii 8800 GTS 128 rdzeni, a 8800 Ultra 1512 rdzeni; dla porównania karta serii NVIDIA Tesla S2050 zawiera 1792 rdzenie;

Pamięć wszystkie rdzenie korzystają ze swobodnego dostępu do pamięci (w oryginale: device memory), która funkcjonuje niezależnie od pamięci operacyjnej komputera macierzystego (w oryginale: host memory) pamięć karty CUDA posługuje się własną przestrzenią adresową; wielkość dostępnej pamięci zmienia się w zależności od wykonania i w kartach 8800 GTS sięgała 1940 MB, 8800 GTX 1800 MB, 8800 Ultra 2160 MB i 24576 MB na karcie NVIDIA Tesla S2050;

Komunikacja interfejs programowy architektury CUDA dostarcza wydajnych usług transferu bloków danych do i z pamięci operacyjnej hosta np. poprzez funkcje: cudamemcpy() cudamemcpy2d() cudamemcpy3d() istnieje inny sposób komunikacji z pamięcią hosta, w szczególności kod wykonywany na rdzeniu GPU może mieć możliwości sięgania do danych znajdujących się poza własną przestrzenią adresową karty (o tym przy okazji)

Pamięć dzielona wszystkie rdzenie mają dostęp do szybkiej pamięci lokalnej (niezależnej funkcjonalnie od reszty pamięci operacyjnej karty), która może być wykorzystywana jako pamięć podręczna dla danych wykorzystywanych szczególnie intensywnie przez kod wykonywany przez rdzenie; typowy rozmiar tej pamięci to 16KB

Jak to wygląda?

API środowisko programisty definiowane przez CUDA SDK dostarcza zestawu środków służących do zarządzania pamięcią urządzenia, a w szczególności do: przydzielania bloku pamięci (cudamalloc(), cudamallocpitch(), cudamalloc3d()) zwalniania bloku pamięci (cudafree()); słowo kluczowe shared, stanowiące część rozszerzonego dialektu języka C używanego w implementacji CUDA SKD, służy do deklarowania danych przeznaczonych do przechowywania w szybkiej pamięci dzielonej

Kod źródłowy kod wynikowy, przeznaczony do wykonania na rdzeniach architektury CUDA w chwili obecnej uzyskuje się na dwa sposoby: poprzez wykorzystanie języka niskiego poziomu (asemblera), odwzorowującego listę rozkazów architektury (język PTX ang. Parallel Thread Execution) poprzez wykorzystanie języków wysokiego poziomu, rozbudowanych - bądź to na poziomie składni, bądź poprzez wykorzystanie zewnętrznych bibliotek - o konstrukcje umożliwiające jawne kontrolowanie zachowania rdzeni

Kod źródłowy w typowym przypadku z jednego, wspólnego kodu źródłowego uzyskuje się dwuczęściowy kod wykonywalny: jedna z części przeznaczona jest do uruchomieniu w środowisku hosta (tu znajduje się prolog i epilog programu, zawierający m.in. inicjację sprzętu karty) druga część zawiera kod przeznaczony do wykonania na rdzeniach urządzenia CUDA; chwili obecnej NVIDIA dostarcza środowiska typu SDK dla języków C/C++ i Fortran oraz platform MS Windows i Linux

Skalowalność interfejs programowany, udostępniany przez architekturę CUDA, gwarantuje, że przy umiejętnym wykorzystaniu jego udogodnień kod wynikowy jest w pełni skalowalny oznacza to między innymi, że może być bez konieczności powtórnej kompilacji wykonywany na silniejszych (w tym również jeszcze nie istniejących) modelach kart CUDA z pełnym wykorzystaniem przyrostu liczby dostępnych rdzeni;

Dialekt CUDA C/C++ dialekt języka C, wykorzystywany do kodowania programów dla rdzeni CUDA, jest podzbiorem języka wzorcowego, a najważniejsze nałożone ograniczenia to: niemożność wykorzystywania rekurencji wykluczenie możliwości posługiwania się wskaźnikami do funkcji oraz funkcjami ze zmienną liczbą parametrów implementacja arytmetyki zmiennopozycyjnej w architekturze CUDA odbiega od definicji zawartej w normie IEEE 754

Rozszerzenia dialekt języka CUDA C zawiera także kilka rozszerzeń, w szczególności dodatkowych deklaratorów i specyfikatorów, pozwalających wprowadzać do kodu źródłowego byty swoiste dla środowiska CUDA; ocenę elegancji tych rozszerzeń pozostawimy programistom...

Host vs device kod wynikowy CUDA jest wykonywany dopiero na żądanie emitowane z kodu hosta; kod CUDA wykonywany jest na wszystkich rdzeniach jednocześnie

Wątki kod wykonywany indywidualnie na pojedynczym rdzeniu nosi nazwę wątku (ang. thread); środki dostępne w środowisku CUDA pozwalają wątkowi na dokładne zidentyfikowanie rdzenia, na którym jest wykonywany, co z kolei umożliwia różnicowanie zachowania algorytmu w zależności od np. rozmiaru danych lub liczby dostępnych rdzeni; taka filozofia przetwarzania pozwala zakwalifikować architekturę CUDA do paradygmatu przetwarzania strumieniowego;

Synchronizacja środowisko CUDA nie zapewnia żadnych mechanizmów synchronizacji poza elementarnym mechanizmem bariery, zatrzymującej wykonanie wątku do momentu osiągnięcia tej bariery przez wątki na wszystkich rdzeniach; operację ten wykonuje się wywołując bezparametrową funkcję usługę środowiska CUDA o nazwie syncthreads(); jakiekolwiek inne mechanizmy synchronizacji wątków muszą zostać zaimplementowanie przez programistę z wykorzystaniem np. dostępu do pamięci dzielonej wątków.

Kod wątków tekst źródłowy kodu przeznaczony do uruchomienia w ramach wątku musi zostać jawnie spreparowany przez programistę; na poziomie języka C/C++ dokonuje się tego poprzez wydzielenie w kodzie kompletnej funkcji opatrzonej specyfikatorem global (jest to słowo kluczowe dialektu CUDA) wymaga się, aby funkcja taka była zadeklarowana jako nie zwracająca wyniku (void); funkcje tego rodzaju w terminologii dokumentów NVIDIA SDK nazywa się mianem kernel.

Kod wątków każdy kernel, zadeklarowany w kodzie źródłowym, stanie się treścią (tekstem) wszystkich wątków uruchomionych równolegle na każdym z procesorów architektury CUDA uruchomienie wątków następuje w wyniku wywołania funkcji deklarowanej dla każdego kernela,

Odpalenie wątku wywołanie funkcji wątku przybiera w dialekcie CUDA C postać poniższą* kernname<<<blocksnum,threadsperblocks>>>(par1,par2); *) podano jeden z prostszych wariantów

Odpalenie wątku kernname<<<blocksnum,threadsperblocks>>>(par1,par2); gdzie: kernelname jest nazwą funkcji kernela zadeklarowanej z zasięgu osiągalnym z miejsca wywołania

Odpalenie wątku kernname<<<blocksnum,threadsperblocks>>>(par1,par2); gdzie: blocksnum jest wyrażeniem typu int, określającym liczbę tzw. bloków wątków, które będą uruchamiane kolejno w celu odpalenia (ang. launch) żądanej liczby wątków

Odpalenie wątku kernname<<<blocksnum,threadsperblocks>>>(par1,par2); gdzie: threadsperblocks jest wyrażeniem typu int, określającym liczbę wątków, które zostaną odpalone wewnątrz każdego z bloków; wymaga się, aby liczba ta nie przewyższała liczby procesorów dostępnych w konkretnym środowisku

Odpalenie wątku kernname<<<blocksnum,threadsperblocks>>>(par1,par2); gdzie: par i są parametrami aktualnymi o liczbie i typach określonych w deklaracjach parametrów formalnych zdefiniowanych w nagłówku wywoływanego kernela.

Odpalenie wątku Formalizm ten daje prosty i efektywny sposób samoskalowania się kodu w zależności od architektury docelowej i liczby dostępnych procesorów. Jeśli rozwiązanie pewnego problemu wymaga równoległego wykonania N wątków, a architektura docelowa udostępnia M procesorów, można założyć, że: threadsperblock=m blocksnum=(n+threadsperblock 1)/threadsPerBlock

Odpalenie wątku UWAGA: wszystkie wątki w bloku wykonują się równolegle wszystkie bloki wątków wykonują się sekwencyjnie

Co ma wątek? Odpalony wątek ma możliwość ustalenia: w ramach którego z bloków pracuje na którym procesorze w bloku został odpalony to daje możliwość zbudowania takiego kodu kernela, który będzie modyfikował swoje działanie np. w zależności od momentu jego uruchomienia

Skalowalność

Trywialny przypadek wymagana liczba wątków nie dzieli się bez reszty przez wyznaczoną liczbę bloków część wątków w ostatnim bloku powinna pozostać bezczynna, tzn. zakończyć pracę natychmiast po odpaleniu.

Rozwiązanie predefiniowane zmienne (struktury): blockidx i threadidx ilustracja sposobu, w jaki wątek zabezpiecza się przed odpaleniem swojego kodu na rzecz nieistniejącego elementu tablicy T[N]: if(blockidx.x * threadsperblock + threadidx.x < N) { // kod przetwarzający element tablicy }

W praktyce krok #1 I stała się jasność... array Host s Memory GPU Card s Memory

W praktyce krok #2 rezerwujemy obszar w pamięci urządzenia array Host s Memory array_d GPU Card s Memory

W praktyce krok #3 Transferujemy dane... array Host s Memory array_d GPU Card s Memory

W praktyce krok #4 Odpalamy obliczenia... GPU MPs array Host s Memory array_d GPU Card s Memory

W praktyce krok #5 Transferujemy wyniki array Host s Memory array_d GPU Card s Memory

W praktyce krok #5 Zwalniamy pamięć... array Host s Memory GPU Card s Memory

Przykład #1 // dodawanie wektorów global void VecAdd(float* A, float* B, float* C) { int i = threadidx.x; C[i] = A[i] + B[i]; } : : int main() { : : VecAdd<<<1, N>>>(A, B, C); }

Przykład #2 // dodawanie macierzy _global void MatAdd (float A[N][N], float B[N][N],float C[N][N]) { int i = threadidx.x; int j = threadidx.y; C[i][j] = A[i][j] + B[i][j]; } int main() { : : //1 blok złożony z N * N * 1 wątków int numblocks = 1; dim3 threadsperblock(n, N); MatAdd<<<numBlocks, threadsperblock>>>(a, B, C); }