CUDA PROGRAMOWANIE PIERWSZE PROSTE PRZYKŁADY RÓWNOLEGŁE. Michał Bieńkowski Katarzyna Lewenda



Podobne dokumenty
Programowanie kart graficznych

Wprowadzenie do programowania w środowisku CUDA. Środowisko CUDA

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 NVIDIA (rdzenie CUDA) Wykład nr 1

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

Programowanie Współbieżne

Lab 9 Podstawy Programowania

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

Programowanie procesorów graficznych w CUDA.

Programowanie współbieżne Wykład 2. Iwona Kochańska

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

Julia 4D - raytracing

Podstawy programowania. Wykład 7 Tablice wielowymiarowe, SOA, AOS, itp. Krzysztof Banaś Podstawy programowania 1

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

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main.

1 Podstawy c++ w pigułce.

Wskaźniki. Przemysław Gawroński D-10, p marca Wykład 2. (Wykład 2) Wskaźniki 8 marca / 17

Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy. Wykład 6. Karol Tarnowski A-1 p.

Język ludzki kod maszynowy

1 Podstawy c++ w pigułce.

CUDA. cudniejsze przyk ady

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

Szablony funkcji i szablony klas

Programowanie w Turbo Pascal

Wstęp do Informatyki zadania ze złożoności obliczeniowej z rozwiązaniami

Tablice i struktury. czyli złożone typy danych. Programowanie Proceduralne 1

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

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

Typy złożone. Struktury, pola bitowe i unie. Programowanie Proceduralne 1

Przygotowanie kilku wersji kodu zgodnie z wymogami wersji zadania,

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

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

Niezwykłe tablice Poznane typy danych pozwalają przechowywać pojedyncze liczby. Dzięki tablicom zgromadzimy wiele wartości w jednym miejscu.

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

Przykładowe sprawozdanie. Jan Pustelnik

Wstęp do Programowania, laboratorium 02

Część 4 życie programu

Widoczność zmiennych Czy wartości każdej zmiennej można zmieniać w dowolnym miejscu kodu? Czy można zadeklarować dwie zmienne o takich samych nazwach?

Wskaźniki. Programowanie Proceduralne 1

Języki i techniki programowania Ćwiczenia 2

Programowanie procesorów graficznych GPGPU

Obiektowy PHP. Czym jest obiekt? Definicja klasy. Składowe klasy pola i metody

Jak napisać program obliczający pola powierzchni różnych figur płaskich?

Raport Hurtownie Danych

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 1

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 4 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 44

Programowanie obiektowe, wykład nr 7. Przegląd typów strukturalnych - klasy i obiekty - c.d.

Rozwiązanie. #include <cstdlib> #include <iostream> using namespace std;

Wskaźniki i dynamiczna alokacja pamięci. Spotkanie 4. Wskaźniki. Dynamiczna alokacja pamięci. Przykłady

int tab[5]; tab[1]; ciągły obszar pamięci, w którym umieszczone są elementy tego samego typu macierz [ ] - dwuargumentowy operator indeksowania

Wstęp do programowania INP003203L rok akademicki 2016/17 semestr zimowy. Laboratorium 1. Karol Tarnowski A-1 p.

PARADYGMATY PROGRAMOWANIA Wykład 4

Spis treści. I. Skuteczne. Od autora... Obliczenia inżynierskie i naukowe... Ostrzeżenia...XVII

Zad. 3: Układ równań liniowych

Dla każdej operacji łącznie tworzenia danych i zapisu ich do pliku przeprowadzić pomiar czasu wykonania polecenia. Wyniki przedstawić w tabelce.

Wykład 1_2 Algorytmy sortowania tablic Sortowanie bąbelkowe

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

1 Wprowadzenie do algorytmiki

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

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

utworz tworzącą w pamięci dynamicznej tablicę dwuwymiarową liczb rzeczywistych, a następnie zerującą jej wszystkie elementy,

Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy. Wykład 1. Karol Tarnowski A-1 p.

Skalowalność obliczeń równoległych. Krzysztof Banaś Obliczenia Wysokiej Wydajności 1

Programowanie CUDA informacje praktycznie i. Wersja

> C++ wskaźniki. Dane: Iwona Polak. Uniwersytet Śląski Instytut Informatyki 26 kwietnia 2017

Pętle i tablice. Spotkanie 3. Pętle: for, while, do while. Tablice. Przykłady

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie.

Podstawy programowania C. dr. Krystyna Łapin

Nowoczesne technologie przetwarzania informacji

Część XVII C++ Funkcje. Funkcja bezargumentowa Najprostszym przypadkiem funkcji jest jej wersja bezargumentowa. Spójrzmy na przykład.

Wprowadzenie do języka Java

LABORATORIUM 3 ALGORYTMY OBLICZENIOWE W ELEKTRONICE I TELEKOMUNIKACJI. Wprowadzenie do środowiska Matlab

Zaawansowane algorytmy i struktury danych

Podstawy programowania. Wykład Pętle. Tablice. Krzysztof Banaś Podstawy programowania 1

Język skryptowy: Laboratorium 1. Wprowadzenie do języka Python

WYKŁAD 8. Funkcje i algorytmy rekurencyjne Proste przykłady. Programy: c3_1.c..., c3_6.c. Tomasz Zieliński

Języki C i C++ Wykład: 2. Wstęp Instrukcje sterujące. dr Artur Bartoszewski - Języki C i C++, sem. 1I- WYKŁAD

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

Programowanie - wykład 4

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

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 5 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 41

Wprowadzenie do programowania w środowisku CUDA. Środowisko CUDA

Implementacja sieci neuronowych na karcie graficznej. Waldemar Pawlaszek

Programowanie i struktury danych

Wstęp do programowania INP001213Wcl rok akademicki 2018/19 semestr zimowy. Wykład 4. Karol Tarnowski A-1 p.

Tablice, funkcje, wskaźniki - wprowadzenie

Podstawy programowania w języku C++

Programowanie i struktury danych

Podstawy języka C++ Maciej Trzebiński. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. Praktyki studenckie na LHC IVedycja,2016r.

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 16 kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 27

wykład II uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C - funkcje, tablice i wskaźniki wykład II dr Jarosław Mederski Spis

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

Wprowadzenie do szablonów szablony funkcji

Wprowadzenie do szablonów szablony funkcji

Functionalization. Funkcje w C. Marcin Makowski. 30 listopada Zak lad Chemii Teoretycznej UJ

Programowanie strukturalne i obiektowe. Funkcje

Podstawy języka C++ Maciej Trzebiński. Praktyki studenckie na LHC IFJ PAN. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. M. Trzebiński C++ 1/16

Podstawy programowania komputerów

Rekurencja (rekursja)

Transkrypt:

PROGRAMOWANIE RÓWNOLEGŁE PIERWSZE PROSTE PRZYKŁADY Michał Bieńkowski Katarzyna Lewenda

Programowanie równoległe Dodawanie wektorów SPIS TREŚCI Fraktale Podsumowanie Ćwiczenia praktyczne

Czym jest? PROGRAMOWANIE RÓWNOLEGŁE Prawo Amdahla Prawo Gustafsona Porównanie Przykładowe zadania

Programowanie równoległe Czym jest? Obliczenia równoległe to takie, w których wiele operacji obliczeniowych wykonuje się jednocześnie w ramach dostępnych jednostek obliczeniowych (procesorów, rdzeni, węzłów obliczeniowych). Bardzo często duże problemy obliczeniowe mogą byd podzielone na mniejsze podproblemy, które mogą wykonywad się jednocześnie. Proces modyfikacji istniejącego kodu tak, aby można go było uruchomid równolegle nazywamy zrównoleglaniem kodu.

Czym jest? PROGRAMOWANIE RÓWNOLEGŁE Prawo Amdahla Prawo Gustafsona Porównanie Przykładowe zadania

Programowanie równoległe Prawo Amdahla Zakłada, że duży problem składa się z takich części, które udaje się zrównoleglid i z takich, dla których nie jest to możliwe. Fragmenty, które nie mogą byd zrównoleglone ograniczają możliwe do osiągnięcia przyspieszenie całego procesu. Często wykorzystywane w przypadku prowadzenia obliczeo równoległych do przewidzenia teoretycznego maksymalnego wzrostu szybkości obliczeo przy użyciu wielu procesorów.

Programowanie równoległe Prawo Amdahla Przyspieszenie algorytmu jest równe: S n = T 1 T n = 1 F + 1 F n Gdzie: T czas wykonania algorytmu, F udział części nierównoległej, n liczba procesorów.

Programowanie równoległe Prawo Amdahla Przykład: 1 h 1 h 2 h 1 h 1 h 1 h 1 h

Programowanie równoległe Prawo Amdahla Dane: F = 50% = 0,5 n = 2 Rozwiązanie: S 2 = 1 1 2 + 1 1 2 2 = 1 1 1 2 + 2 2 = 1 1 2 + 1 4 = 1 3 4 = 4 3 1,3 Odpowiedź: Teoretyczne przyspieszenie algorytmu wynosi 1,3.

Czym jest? PROGRAMOWANIE RÓWNOLEGŁE Prawo Amdahla Prawo Gustafsona Porównanie Przykładowe zadania

Programowanie równoległe Prawo Gustafsona Zakłada, że każdy wystarczająco duży problem może byd efektywnie zrównoleglony. Odnosi się do wad prawa Amdahla, które nie jest skalowalne do tego stopnia, aby brad pod uwagę dostępnośd mocy obliczeniowej przy rozrastaniu się maszyny. Usuwa problem ustalonego rozmiaru problemu lub ustalonego ładowania obliczeo na równoległych procesorach. Zamiast tego proponuje koncepcje ustalonego czasu, która prowadzi do skalowanego przyspieszenia.

Programowanie równoległe Prawo Gustafsona Przyspieszenie algorytmu jest równe: S P = P α P 1 Gdzie: P ilośd procesorów, S przyspieszenie, α częśd programu, której nie da się zrównoleglid.

Programowanie równoległe Prawo Gustafsona Przykład: 1 h 1 h 4 h 2 h 2 h 1 h 1 h

Programowanie równoległe Prawo Gustafsona Dane: P = 2 α 0,3 Rozwiązanie: S 2 = 2 0,3 2 1 = 2 0,3 = 1,7 Odpowiedź: Teoretyczne przyspieszenie algorytmu wynosi 1,7.

Czym jest? PROGRAMOWANIE RÓWNOLEGŁE Prawo Amdahla Prawo Gustafsona Porównanie Przykładowe zadania

Programowanie równoległe Porównanie Prawo Amdahla jedna ciężarówka jest w stanie przewieźd z punktu A do B jedną tonę towaru w ciągu 9 godzin. Pomoc dodatkowych ośmiu ciężarówek nie spowoduje skrócenia tego czasu do jednej godziny. Prawo Gustafsona 9 ciężarówek jest w stanie przewieźd z punktu A do punktu B 9 ton towaru w ciągu 9 godzin.

Czym jest? PROGRAMOWANIE RÓWNOLEGŁE Prawo Amdahla Prawo Gustafsona Porównanie Przykładowe zadania

Programowanie równoległe Przykładowe zadania Porównywanie danych, Obliczanie liczby π metodą Monte Carlo, Operacje macierzowe, Algorytm sortowania QuickSort, Rozwiązywanie układów równao liniowych, Obliczanie sieci neuronowych.

Programowanie równoległe Dodawanie wektorów SPIS TREŚCI Fraktale Podsumowanie Ćwiczenia praktyczne

Teoria DODAWANIE WEKTORÓW C/C++ C Porównanie Podsumowanie

Dodawanie wektorów Teoria Dodawanie wektorów polega na zwykłym dodawaniu elementów znajdujących się na odpowiadających sobie pozycjach. Wyniki zapisywane są w trzeciej tablicy. 5 3 6 3 1 9 2 6 1 0 + 2 5 7 1 4 0 4 3 6 8 = 7 8 13 4 5 9 6 9 7 8

Teoria DODAWANIE WEKTORÓW C/C++ C Porównanie Podsumowanie

Dodawanie wektorów C/C++ int main() int *a, *b, *c; int size = N * sizeof(int); a = (int *)malloc(size); b = (int *)malloc(size); c = (int *)malloc(size); for (int i=0; i<n; i++) a[i] = rand() % 100; b[i] = rand() % 100; void add(int *a, int *b, int *c, int n) int index = 0; while(index < N) c[index] = a[index] + b[index]; index++; add(a, b, c); for (int i=0; i<n; i++) printf("%d + %d = %d\n", a[i], b[i], c[i]); free(a); free(b); free(c); return 0;

Dodawanie wektorów C/C++ Zrównoleglanie obecnej funkcji add() wydaje się bardzo proste. Wystarczy: Zmienid wartośd inkrementacji, Zainicjowad wartośd index odpowiednio dla każdego procesora. Rdzeo 1 void add(int *a, int *b, int *c) int index = 0; Rdzeo 2 void add(int *a, int *b, int *c) int index = 1; while(index < N) c[index] = a[index] + b[index]; index += 2; while(index < N) c[index] = a[index] + b[index]; index += 2;

Dodawanie wektorów C/C++ Ostatecznie możemy wprowadzid dodatkowe argumenty do funkcji add(): void add(int *a, int *b, int *c, int id, int cores) int index = id; while(index < N) c[index] = a[index] + b[index]; index += cores; Niestety o ile zmiana kodu funkcji add() jest prosta to samo uruchomienie tego kodu, aby działał zgodnie z założeniami wymagania napisania sporej ilości dodatkowego kodu.

Teoria DODAWANIE WEKTORÓW C/C++ C Porównanie Podsumowanie

Dodawanie wektorów C Hello world Jest to pierwszy program C więc napiszmy go od podstaw: int main() printf("hello world\n"); return 0; Standardowy kod języka C wykonuje się na procesorze gospodarza (host). Kompilator NVIDIA może byd użyty do kompilowania programów bez kodu urządzenia (device).

Dodawanie wektorów C Hello world z kodem urządzenia Dopiszmy kod urządzenia oraz jego najprostsze wywołanie: int main() kernel<<< 1, 1 >>>(); printf("hello world\n"); global void kernel() // Brak instrukcji return 0; Słowo kluczowe global wskazuje funkcję, która: Uruchamia się na urządzeniu (device), Wywoływana jest z kodu gospodarza (host). W potrójnych nawiasach występują dodatkowe opcje wywołania funkcji. * Argumenty znajdujące się w <<<( )>>> zostaną opisane w dalszej części prezentacji.

Dodawanie wektorów C Hello world z kodem urządzenia dodający dwie liczby int main() int a, b, c; int *d_a, *d_b, *d_c; int size = sizeof(int); global void add(int *a, int *b, int *c) *c = *a + *b; cudamalloc((void **)&d_a, size); cudamalloc((void **)&d_b, size); cudamalloc((void **)&d_c, size); a = 5; b = 3; cudamemcpy(d_a, &a, size, cudamemcpyhosttodevice); cudamemcpy(d_b, &b, size, cudamemcpyhosttodevice); add<<< 1, 1 >>>(d_a, d_b, d_c); cudamemcpy(&c, d_c, size, cudamemcpydevicetohost); printf("%d + %d = %d\n", a, b, c); cudafree(d_a); cudafree(d_b); cudafree(d_c); return 0;

Dodawanie wektorów C Równoległe dodawanie wektorów z wykorzystaniem bloków Chcąc uruchomid kod równoległe zmieniamy argumenty wywołania funkcji: add<<< 1, 1 >>>(d_a, d_b, d_c); add<<< N, 1 >>>(d_a, d_b, d_c); Zmiana pierwszego argumentu z wartości 1 na N spowoduje wywołanie funkcji add() N razy. Korzystając z funkcji add() wywoływanej równolegle możemy dodad do siebie dwa wektory. Każde równoległe wywołanie funkcji add() jest określane jako blok. Zbiór wszystkich bloków określamy jako siatkę. Każda wywołana funkcja add() może odczytad numer swojego bloku używając zmiennej blockidx.x.

Dodawanie wektorów C Równoległe dodawanie wektorów z wykorzystaniem bloków Funkcja add() wykorzystująca numer bloku jako indeks w tablicy: global void add(int *a, int *b, int *c) c[blockidx.x] = a[blockidx.x] + b[blockidx.x]; Reprezentacja graficzna: Blok 0 c[0] = a[0] + b[0]; Blok 1 c[1] = a[1] + b[1]; Blok 2 Blok 3 c[2] = a[2] + b[2]; c[3] = a[3] + b[3];

Dodawanie wektorów C Równoległe dodawanie wektorów z wykorzystaniem bloków #define N (2048*2048) add<<< N, 1 >>>(d_a, d_b, d_c); int main() int *a, *b, *c; int *d_a, *d_b, *d_c; int size = N * sizeof(int); a = (int *)malloc(size); b = (int *)malloc(size); c = (int *)malloc(size); cudamalloc((void **)&d_a, size); cudamalloc((void **)&d_b, size); cudamalloc((void **)&d_c, size); for(int i=0; i<n; i++) a[i] = rand() % 100; b[i] = rand() % 100; cudamemcpy(c, d_c, size, cudamemcpydevicetohost); for(int i=0; i<n; i++) printf("%d + %d = %d\n", a[i], b[i], c[i]); free(a); free(b); free(c); cudafree(d_a); cudafree(d_b); cudafree(d_c); return 0; cudamemcpy(d_a, a, size, cudamemcpyhosttodevice); cudamemcpy(d_b, b, size, cudamemcpyhosttodevice);

Dodawanie wektorów C Równoległe dodawanie wektorów z wykorzystaniem wątków Każde wywołanie funkcji może zostad podzielone na wątki. Porównajmy równoległe wywołania względem bloków oraz wątków. Bloki global void add(int *a, int *b, int *c) c[blockidx.x] = a[blockidx.x] + b[blockidx.x]; add<<< N, 1 >>>(d_a, d_b, d_c); Wątki global void add(int *a, int *b, int *c) c[threadidx.x] = a[threadidx.x] + b[threadidx.x]; add<<< 1, N >>>(d_a, d_b, d_c);

Dodawanie wektorów C Równoległe dodawanie wektorów z wykorzystaniem bloków oraz wątków Jak do tej pory widzieliśmy w jaki sposób dodajemy wektory z użyciem: Bloków, Wątków. Połączmy oba sposoby:

Dodawanie wektorów C Równoległe dodawanie wektorów z wykorzystaniem bloków oraz wątków Chcąc odwoład się do konkretnego elementu wektora nie wystarczy już tylko użyd blockidx.x lub threadidx.x. Przykładowa reprezentacja graficzna wywołania z 4 blokami oraz 8 wątkami dla wektora o długości 32 elementów: 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 r r r blockid.x = 0 blockid.x = 1 blockid.x = 2 blockid.x = 3 Odnalezienie indeksu wektora sprowadza się do obliczenia wartości M = ilość wątków na blok, dla której: int index = threadidx.x + blockidx.x * M;

Dodawanie wektorów C Równoległe dodawanie wektorów z wykorzystaniem bloków oraz wątków W celu ułatwienia zamiast wyznaczad za każdym razem wartośd zmiennej M możemy skorzystad z danych wbudowanych: M = blockdim.x // Wyraża ilość wątków dla pojedynczego bloku Funkcja add() po zmianach wygląda zatem następująco: global void add(int *a, int *b, int *c) int index = threadidx.x + blockidx.x * blockdim.x; c[index] = a[index] + b[index]; Funkcja main() również wymaga drobnych zmian. Należy bowiem odpowiednio wywoład add().

Dodawanie wektorów C Równoległe dodawanie wektorów z wykorzystaniem bloków oraz wątków #define N (2048*2048) #define THREADS_PER_BLOCK 512 int main() int *a, *b, *c; int *d_a, *d_b, *d_c; int size = N * sizeof(int); a = (int *)malloc(size); b = (int *)malloc(size); c = (int *)malloc(size); cudamalloc((void **)&d_a, size); cudamalloc((void **)&d_b, size); cudamalloc((void **)&d_c, size); for(int i=0; i<n; i++) a[i] = rand() % 100; b[i] = rand() % 100; add<<< N/THREADS_PER_BLOCK, THREADS_PER_BLOCK >>>( d_a, d_b, d_c ); cudamemcpy(c, d_c, size, cudamemcpydevicetohost); for(int i=0; i<n; i++) printf("%d + %d = %d\n", a[i], b[i], c[i]); free(a); free(b); free(c); cudafree(d_a); cudafree(d_b); cudafree(d_c); return 0; cudamemcpy(d_a, a, size, cudamemcpyhosttodevice); cudamemcpy(d_b, b, size, cudamemcpyhosttodevice);

Dodawanie wektorów C Równoległe dodawanie wektorów z wykorzystaniem bloków oraz wątków Niestety w takim kodzie mogą wystąpid błędy: Niecałkowite dzielenie N/THREADS_PER_BLOCK. Rozwiązanie: int M = THREADS_PER_BLOCK; add<<< (N + M-1) / M, M >>>(d_a, d_b, d_c); Wyjście poza zakres wektora. Rozwiązanie: global void add(int *a, int *b, int *c, int n) int index = threadidx.x + blockidx.x * blockdim.x; if (index < n) c[index] = a[index] + b[index]; add<<< (N + M-1) / M, M >>>(d_a, d_b, d_c, N);

Dodawanie wektorów C Równoległe dodawanie wektorów z wykorzystaniem bloków oraz wątków Wydaje się, że wątki są niepotrzebne, wprowadzają jedynie dodatkowy kod i zamieszanie. Jednak posiadają dodatkowe atuty, których bloki nie mają, są to: Pamięd współdzielona, Możliwośd komunikacji między sobą, Korzystając z bloków oraz wątków jesteśmy w stanie wykonad więcej obliczeo względem jednego wywołania.

Teoria DODAWANIE WEKTORÓW C/C++ C Porównanie Podsumowanie

Dodawanie wektorów Porównanie #define N (2048*2048) void add(int *a, int *b, int *c) int index = 0; while(index < N) c[index] = a[index] + b[index]; index++; int main() int *a, *b, *c; int size = N * sizeof(int); a = (int *)malloc(size); b = (int *)malloc(size); c = (int *)malloc(size); #define N (2048*2048) #define THREADS_PER_BLOCK 512 global void add(int *a, int *b, int *c, int n) int index = threadidx.x + blockidx.x * blockdim.x; if (index < n) c[index] = a[index] + b[index]; int main() int *a, *b, *c; int *d_a, *d_b, *d_c; int size = N * sizeof(int); a = (int *)malloc(size); b = (int *)malloc(size); c = (int *)malloc(size); cudamalloc((void **)&d_a, size); cudamalloc((void **)&d_b, size); cudamalloc((void **)&d_c, size);

Dodawanie wektorów Porównanie for (int i=0; i<n; i++) a[i] = rand() % 100; b[i] = rand() % 100; for(int i=0; i<n; i++) a[i] = rand() % 100; b[i] = rand() % 100; cudamemcpy(d_a, a, size, cudamemcpyhosttodevice); cudamemcpy(d_b, b, size, cudamemcpyhosttodevice); add(a, b, c); add<<< (N + THREADS_PER_BLOCK-1) / THREADS_PER_BLOCK, THREADS_PER_BLOCK >>>(d_a, d_b, d_c, N); cudamemcpy(c, d_c, size, cudamemcpydevicetohost); for (int i=0; i<n; i++) printf("%d + %d = %d\n", a[i], b[i], c[i]); free(a); free(b); free(c); for(int i=0; i<n; i++) printf("%d + %d = %d\n", a[i], b[i], c[i]); free(a); free(b); free(c); cudafree(d_a); cudafree(d_b); cudafree(d_c); return 0; return 0;

Teoria DODAWANIE WEKTORÓW C/C++ C Porównanie Podsumowanie

Dodawanie wektorów Podsumowanie Zrównolaglenie kodu na potrzeby C nie wymaga dużych zmian. Należy starannie dobierad ilośd bloków oraz wątków. Przed ustaleniem ilości bloków oraz wątków należy sprawdzid jak dużo z wymienionych wartości jest w stanie obsłużyd karta graficzna. Przy dodawaniu krótkich wektorów należy unikad obliczeo na układach GPU ze względu na długi czas kopiowania danych z hosta do urządzenia i odwrotnie.

Programowanie równoległe Dodawanie wektorów SPIS TREŚCI Fraktale Podsumowanie Ćwiczenia praktyczne

Teoria Pseudokod FRAKTALE C Porównanie wydajności CPU oraz GPU Podsumowanie

Fraktale Teoria Fraktal figura geometryczna o złożonej strukturze, którą cechuje samopodobieostwo, tzn. podobieostwo fraktala do jego części. Zbiór Julii fraktal będący także podzbiorem płaszczyzny zespolonej. Wzór ogólny: z 0 = p z n+1 = z 2 n + c Gdzie: z n - liczba zespolona p punkt na płaszczyźnie, c stała.

Fraktale Teoria Przykładowy fraktal Julii

Fraktale Teoria Działania na liczbach zespolonych Liczba zespolona składa się z części rzeczywistej z r oraz części urojonej z i. z = z r + iz i Potęgowanie: z 2 = z r 2 z i 2 + i(2 z r z i ) Dodawanie: Moduł: a + b = a r + b r + i a i + b i z = z r 2 + z i 2

Teoria Pseudokod FRAKTALE C Porównanie wydajności CPU oraz GPU Podsumowanie

Fraktale Pseudokod getcolorlevel(complex c, Complex p) begin i := 0; z := p; until ( z < 4) and (i < maxiter) do z = z^2 + c; i := i + 1; end; return i; end; Gdzie: C - liczba zespolona służąca generowaniu zbioru Julii P - liczba zespolona obliczona dla odpowiedniego punktu płaszczyzny

Teoria Pseudokod FRAKTALE C Porównanie wydajności CPU oraz GPU Podsumowanie

Fraktale C Zmienne const int MAX_LEVEL = 255; const int THREADS_PER_BLOCK = 512; int main() unsigned char **colorsarray; unsigned char *fractallevelscpu; unsigned char *fractallevelsgpu; float minx = -1.7; float maxx = 1.7; float miny = -1.3; float maxy = 1.3; float input_re = -0.79; float input_im = 0.1463; int width = 500; int height = 380; float stepx = (maxx - minx) / (float) width; float stepy = (maxy - miny) / (float) height; int BLOCKS = (width + THREADS_PER_BLOCK-1) / THREADS_PER_BLOCK;

Fraktale C Alokacja pamięci oraz wartości domyślne colorsarray = (unsigned char**) malloc((max_level+1) * sizeof(unsigned char*)); for(int i=0; i<=max_level; i++) colorsarray[i] = (unsigned char *) malloc(3 * sizeof(unsigned char)); colorsarray[i][0] = (int) (255.0 * i / MAX_LEVEL); colorsarray[i][1] = (int) (255.0 * log((float) i) / log((float) MAX_LEVEL)); colorsarray[i][2] = (int) (255.0 * i / MAX_LEVEL); fractallevelscpu = (unsigned char*) malloc(width * sizeof(unsigned char)); cudamalloc((unsigned char **) &fractallevelsgpu, width * sizeof(unsigned char)); createbitmapfile((...)); for(int h = 0; h < height; h++) fractalgpu<<< BLOCKS, THREADS_PER_BLOCK >>>(fractallevelsgpu, h, (...)); cudamemcpy(fractallevelscpu, fractallevelsgpu, width * sizeof(unsigned char), cudamemcpydevicetohost); appendbitmapfile((...));

Fraktale C Obliczanie fraktala, zapis do pliku oraz czyszczenie pamięci createbitmapfile((...)); for(int h = 0; h < height; h++) fractalgpu<<< BLOCKS, THREADS_PER_BLOCK >>>(fractallevelsgpu, h, (...)); cudamemcpy(fractallevelscpu, fractallevelsgpu, width * sizeof(unsigned char), cudamemcpydevicetohost); appendbitmapfile((...)); closebitmapfile(); for(int i=0; i<=max_level; i++) free(colorsarray[i]); free(colorsarray); free(fractallevelscpu); cudafree(fractallevelsgpu); return 0;

Fraktale C Funkcja wykonywana na procesorze GPU global void fractalgpu(unsigned char *a, int y, (...)) int x = blockidx.x * blockdim.x + threadidx.x; if(x < width) float p_re = x * stepx + minx; float p_im = y * stepy + miny; float z_re = p_re; float z_im = p_im; int iteration = 0; while ((z_re * z_re + z_im * z_im) < 4 && iteration < maxlevel) float tmp_re = z_re * z_re - z_im * z_im + c_re; float tmp_im = 2 * z_re * z_im + c_im; z_re = tmp_re; z_im = tmp_im; iteration++; a[x] = iteration;

Teoria Pseudokod FRAKTALE C Porównanie wydajności CPU oraz GPU Podsumowanie

Fraktale Porównanie wydajności CPU oraz GPU Wykres czasu obliczania przykładowego fraktala względem długości boku: 120 100 80 60 40 20 0 0 5000 10000 15000 20000 25000 Czas GPU Czas CPU * Do testów czasowych wyłączono zapis na dysk w celu uniknięcia zakłóceo pomiaru.

Teoria Pseudokod FRAKTALE C Porównanie wydajności CPU oraz GPU Podsumowanie

Fraktale Podsumowanie Testy wydajnościowe wykazały, że do pewnego momentu obliczenia na procesorze graficznym były równie wydajne jak na zwykłym CPU. Wraz ze wzrostem rozdzielczości generowanego obrazu widad, że na procesorze graficznym był osiągany krótszy czas. Obliczenia dwuwymiarowych tablic możemy uprościd obliczając je wiersz po wierszu lub spłaszczyd je do tablic jednowymiarowych i operowad jak na zwykłym wektorze.

Programowanie równoległe Dodawanie wektorów SPIS TREŚCI Fraktale Podsumowanie Ćwiczenia praktyczne

Wnioski PODSUMOWANIE Materiały do pobrania Bibliografia

Podsumowanie Wnioski Im dłużej wykonywane są obliczenia na układzie graficznym tym większą otrzymamy różnicę czasu dla wykonywanego zadania (na korzyśd GPU). Czas wykonania zadania zależy od dobrania odpowiednich wartości w wywołaniu funkcji urządzenia. Układ graficzny ma ograniczenia co do ilości wykonywanych bloków oraz wątków.

Wnioski PODSUMOWANIE Materiały do pobrania Bibliografia

Podsumowanie Materiały do pobrania Cała prezentacja wraz z kodami oraz działającymi programami jest do pobrania pod następującym adresem: http://tnij.org/prezentacja Animacje w postaci filmów dostępne są pod następującym adresem: http://tnij.org/animacje

Wnioski PODSUMOWANIE Materiały do pobrania Bibliografia

Podsumowanie Bibliografia by Example, Jason Sanders, Edward Kandrot www.nvidia.com www.wikipedia.org

Programowanie równoległe Dodawanie wektorów SPIS TREŚCI Fraktale Podsumowanie Ćwiczenia praktyczne

Zakooczenie Ćwiczenia praktyczne Pobrad dostępne materiały z wcześniej udostępnionego linku. Uruchomid programy i zapoznad się z kodem. Napisad dowolny program z wykorzystaniem technologii C.

Dziękujemy za uwagę :) PYTANIA?