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



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

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

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

Programowanie kart graficznych

Programowanie Współbieżne

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

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

Programowanie CUDA informacje praktycznie i. Wersja

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

Programowanie aplikacji równoległych i rozproszonych

CUDA. cudniejsze przyk ady

Wprowadzenie do programowania w środowisku CUDA. Środowisko CUDA

Programowanie CUDA informacje praktycznie i przykłady. Wersja

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

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

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

CUDA ćwiczenia praktyczne

Programowanie procesorów graficznych GPGPU

Programowanie procesorów graficznych w CUDA.

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

i3: internet - infrastruktury - innowacje

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

Programowanie kart graficznych. Kompilator NVCC Podstawy programowania na poziomie API sterownika

Programowanie kart graficznych

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

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

Przygotowanie kilku wersji kodu zgodnie z wymogami wersji zadania,

Obliczenia na GPU w technologii CUDA

Moc płynąca z kart graficznych

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

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

Tesla. Architektura Fermi

Programowanie procesorów graficznych GPGPU

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

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

Programowanie mikrokontrolerów AVR

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

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

Wstęp do Programowania, laboratorium 02

Programowanie Równoległe wykład 12. Thrust C Maciej Matyka Instytut Fizyki Teoretycznej

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

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 8. Karol Tarnowski A-1 p.

Wprowadzenie do programowania w środowisku CUDA. Środowisko CUDA

Struktury. Przykład W8_1

CUDA jako platforma GPGPU w obliczeniach naukowych

Programowanie z wykorzystaniem technologii CUDA i OpenCL Wykład 1

Języki i paradygmaty programowania 1 studia stacjonarne 2018/19. Lab 9. Tablice liczbowe cd,. Operacje na tablicach o dwóch indeksach.

Programowanie kart graficznych. Sprzęt i obliczenia

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

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

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

PMiK Programowanie Mikrokontrolera 8051

Lab 8. Tablice liczbowe cd,. Operacje macierzowo-wektorowe, memcpy, memmove, memset. Wyrażenie warunkowe.

Systemy mobilne. Laboratorium. Dostęp do danych GPS w Windows Phone 7

Linux Kernel III. Character devices

Programowanie - wykład 4

Programowanie I C / C++ laboratorium 03 arytmetyka, operatory

Organizacja pamięci w procesorach graficznych

Wykład 7 Podręczna pamięć buforowa (ang. buffer cache) w systemie Linuks. Wojciech Kwedlo, Systemy Operacyjne II -1- Wydział Informatyki PB

Praca dyplomowa magisterska

Spis treści PLIKI BINARNE W JĘZYKU C. Informatyka 2. Instrukcja do pracowni specjalistycznej z przedmiotu. Numer ćwiczenia INF23

2 Przygotował: mgr inż. Maciej Lasota

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

Raport Hurtownie Danych

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

Jak Windows zarządza pamięcią?

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

Laboratorium Systemów Operacyjnych. Ćwiczenie 4. Operacje na plikach

Julia 4D - raytracing

Spis treści PLIKI BINARNE W JĘZYKU C. Informatyka 2. Instrukcja do pracowni specjalistycznej z przedmiotu. Numer ćwiczenia INF23

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

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

Podstawy programowania w języku C++

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 7 maja K.Grzelak (Wykład 8) Programowanie w C++ 1 / 31

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

Instrukcje sterujące. Programowanie Proceduralne 1

Wstęp do programowania

Programowanie I C / C++ laboratorium 02 Składnia pętli, typy zmiennych, operatory

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

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

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

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

Programowanie równoległe Wprowadzenie do OpenCL. Rafał Skinderowicz

Aplikacja Sieciowa. Najpierw tworzymy nowy projekt, tym razem pracować będziemy w konsoli, a zatem: File->New- >Project

Struktury systemów operacyjnych

Funkcje. Spotkanie 5. Tworzenie i używanie funkcji. Przekazywanie argumentów do funkcji. Domyślne wartości argumentów

Procesory kart graficznych i CUDA wer

Język ludzki kod maszynowy

Programowanie strukturalne język C - wprowadzenie

Języki programowania. Przetwarzanie plików amorficznych Konwencja języka C. Część siódma. Autorzy Tomasz Xięski Roman Simiński

Zaawansowane programowanie w języku C++ Funkcje uogólnione - wzorce

- - Ocena wykonaniu zad3. Brak zad3

Stałe, tablice dynamiczne i wielowymiarowe

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

Janusz Ganczarski. OpenGL Pierwszy program

Microsoft IT Academy kurs programowania

Programowanie mikrokontrolerów AVR z rodziny ATmega.

WYKŁAD 10. Zmienne o złożonej budowie Statyczne i dynamiczne struktury danych: lista, kolejka, stos, drzewo. Programy: c5_1.c, c5_2, c5_3, c5_4, c5_5

Karta przedmiotu. Podstawy programowania procesorów graficznych. realizowanego w ramach projektu PO WER

Algorytm. a programowanie -

Transkrypt:

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

CUDA z OpenGL 1. Dane dla kerneli znajdują się na karcie GFX. 2. Chcemy liczyć i rysować używając tych samych danych bez kopiowania CPU -> GPU -> CPU. 3. CUDA OpenGL interoperability: dane w buforach OpenGL (VBO, PBO) rysujemy bezpośrednio z buforów OpenGL mapujemy bufory na pamięć operacyjną CUDA wywołujemy kernele pracując na mapowanych adresach.

Bufor wierzchołków (OpenGL) Inicjalizacja bufora wierzchołków Dane na CPU float2 points[n]; Indeks bufora wierzchołków (VBO) GLuint pointsvbo; 1. Utworzenie nazwy bufora VBO (to generate) 2. Związanie (to bind) 3. Alokacja i skopiowanie danych (to buffer) glgenbuffers(1,&pointsvbo); glbindbuffer(gl_array_buffer, pointsvbo); glbufferdata(gl_array_buffer, sizeof(points), points, GL_STREAM_DRAW)

Używanie VBO przez CUDA CUDA OpenGL interoperability #include <cuda_gl_interop.h> Zgłoszenie zasobu OpenGL do API CUDA cudagraphicsglregisterbuffer( &pointsvbo_resource, pointsvbo, cudagraphicsmapflagsnone ); Mapowanie zasobu na adres pamięci CUDA cudagraphicsmapresources(1, &pointsvbo_resource, 0);... // pobierz adres bufora VBO... // wywołaj kernel cudagraphicsunmapresources(1, &pointsvbo_resource, 0);

Używanie VBO przez CUDA Pobranie adresu zgłoszonego i zmapowanego VBO float2 *pointsvbo_device; size_t num_bytes; cudagraphicsresourcegetmappedpointer( (void**)&pointsvbo_device, &num_bytes, pointsvbo_resource ); Wywołanie kernela (z przekazaniem adresu) global void movepardevice_vbo(float2 *p_device, float dt) { // p_device[..] =..; } void call_movepar_vbo(float2 *points_device, float dt) { movepardevice_vbo <<< NUM_BLOCKS, MAX_THREAD>>> (points_device, dt); }

Kompilacja LINUX Przetestowane na pracowni 426 Kompilacja CUDA + GLUT (OpenGL) > nvcc main.cpp kernels.cu -lglut lglu >./a.out Kompilacja CUDA + GLUT + GLEW > nvcc main.cpp kernels.cu -lglut lglu -lglew >./a.out

Podsumowanie OpenGL+CUDA Inicjalizuj urządzenie (cudaglsetgldevice(0); ) Inicjalizuj GLUT, GLEW Inicjalizuj dane na CPU Stwórz bufor VBO (lub inny) na karcie Zgłoś bufor do CUDA 1. Mapuj bufor na adres pamięci operacyjnej CUDA 2. Pobierz adres bufora w pamięci CUDA 3. Wywołaj kernel modyfikujący dane w buforze 4. Zwolnij zasoby (Unmap) 5. Idź do 1

(przykład 1000000 punktów)

Problem (426) Zgłoszenie zasobu do CUDA cudagraphicsglregisterbuffer( &pointsvbo_resource, pointsvbo, cudagraphicsmapflagsnone ); Nie działa w pracowni 426 ( GTS 250? ) Kod błędu: UnknownError OpenGL? Compute capability 1.1? Aplikacja przykładowa przetestowana została z sukcesem na: GTX 285 (Windows 7, CUDA 3.2), GTX 260 (Linux), GTX 460 (Linux, Ubuntu, Cuda 4.0)

Sprawdzanie błędów Większość funkcji CUDA zwraca kody błędów, np. cudaerror_t cudagraphicsglregisterbuffer ( struct cudagraphicsresource **resource, Gluint buffer, unsigned int flags ) Ww funkcja może zwrócić np. cudasuccess, cudaerrorinvaliddevice, cudaerrorinvalidvalue, cudaerrorinvalidresourcehandle, cudaerrorunknown Błędy można łatwo sprawdzić (if, switch, etc.)

CUTIL_SAFE_CALL MACRO biblioteki CUTIL Nie wchodzi w oficjalną dystrybucję API CUDA Używane w SDK dla CUDA Ogólnie nie jest polecane używanie CUTIL forum nvidii Ale możemy skorzystać z kodów źródłowych CUTIL: #define CUDA_SAFE_CALL_NO_SYNC( call) { cudaerror err = call; if( cudasuccess!= err) { fprintf(stderr, "Cuda error in file '%s' in line %i : %s.\n", FILE, LINE, cudageterrorstring(err)); exit(exit_failure); } }

Algorytm n Ciał N oddziałujących punktów materialnych Długozasięgowe oddziaływania par Potencjał grawitacyjny Potencjał Lennarda-Jonesa Pętla obliczeniowa: Obliczenie sił Całkowanie równań ruchu

Rozwiązanie 1. CPU Algorytm naiwny z podwójną pętlą - O(n^2) Kod wyznaczający pozycję punktów: (N=32000, 42 sekundy)

Rozwiązanie 2. GPU Algorytm naiwny z podwójną pętlą - O(n^2) Kod wyznaczający pozycję punktów: (N=32000, ~2 sekundy)

Rozwiązanie 3. GPU+pamięć shared Mapowanie wątek -> numer ciała int gtid = blockidx.x * blockdim.x + threadidx.x; N liczba punktów P liczba wątków w bloku N/P liczba bloków

Rozwiązanie 3. GPU+pamięć shared N wątków: 1. k-ty wątek wykonuje pętlę po blokach (i = 0 - N/P) 2. k-ty wątek wpisuje do pamięci shared swojego bloku: shpositions[k] = i * P + k 3. syncthreads(); 4. Akumulacja sił (pętla po shpositions[k]) 5. syncthreads(); 6. Wróć do 2.

global void movepardevice_vbo2(float2 *p_device, float dt) { int k = blockidx.x * blockdim.x + threadidx.x; if(k>=n) return; float2 p, f, v; v = v_device[k]; f = make_float2(0,0); int i,tile; p = p_device[k]; for(tile=0; tile < N / THREADS_PER_BLOCK; tile++) { i = tile * blockdim.x + threadidx.x; shposition[threadidx.x] = p_device[i]; syncthreads(); f = accumulate_tile(p, f); syncthreads(); } } // integrate v.x = v.x + f.x * dt; v.y = v.y + f.y * dt; p.x = p.x + v.x * dt; p.y = p.y + v.y * dt; p_device[k]=p; v_device[k]=v;

global void movepardevice_vbo2(float2 *p_device, float dt) { int k = blockidx.x * blockdim.x + threadidx.x; if(k>=n) return; float2 p, f, v; v = v_device[k]; f = make_float2(0,0); int i,tile; p = p_device[k]; for(tile=0; tile < N / THREADS_PER_BLOCK; tile++) { i = tile * blockdim.x + threadidx.x; shposition[threadidx.x] = p_device[i]; syncthreads(); f = accumulate_tile(p, f); syncthreads(); } } // integrate v.x = v.x + f.x * dt; v.y = v.y + f.y * dt; p.x = p.x + v.x * dt; p.y = p.y + v.y * dt; p_device[k]=p; v_device[k]=v;

global void movepardevice_vbo2(float2 *p_device, float dt) { int k = blockidx.x * blockdim.x + threadidx.x; if(k>=n) return; float2 p, f, v; v = v_device[k]; f = make_float2(0,0); int i,tile; p = p_device[k]; for(tile=0; tile < N / THREADS_PER_BLOCK; tile++) { i = tile * blockdim.x + threadidx.x; shposition[threadidx.x] = p_device[i]; syncthreads(); f = accumulate_tile(p, f); syncthreads(); } } // integrate v.x = v.x + f.x * dt; v.y = v.y + f.y * dt; p.x = p.x + v.x * dt; p.y = p.y + v.y * dt; p_device[k]=p; v_device[k]=v;

global void movepardevice_vbo2(float2 *p_device, float dt) { int k = blockidx.x * blockdim.x + threadidx.x; if(k>=n) return; float2 p, f, v; v = v_device[k]; f = make_float2(0,0); int i,tile; p = p_device[k]; for(tile=0; tile < N / THREADS_PER_BLOCK; tile++) { i = tile * blockdim.x + threadidx.x; shposition[threadidx.x] = p_device[i]; syncthreads(); f = accumulate_tile(p, f); syncthreads(); } } // integrate v.x = v.x + f.x * dt; v.y = v.y + f.y * dt; p.x = p.x + v.x * dt; p.y = p.y + v.y * dt; p_device[k]=p; v_device[k]=v;

Wyznaczenie sił dla kompletnego bloku: device float2 accumulate_tile(float2 p, float2 f) { int i; for(i=0; i < THREADS_PER_BLOCK; i++) f = force(shposition[i], p, f); } return f;

W działaniu N=16000 [uruchom] Porównanie wydajności 1 core CPU vs G80 [animacja]

N80 i n200 Rys: Porównanie wydajności naiwnego algorytmu n-body do wersji z pamięcią shared. różne wyniki dla innych architektur: n80 (lewy) i n200 (prawy) zmniejszone znaczenie pamięci shared efektywniejszy dostęp do pamięci globalnej

Dygresja: przepustowość max Teoretyczna przepustowość naszej karty GTS 250 używa pamięci DDR taktowanej zegarem1100mhz = 1100 x 1e6 =1.1e9 Hz Dostęp przez interfejs 512 bitowy = 64 bajtowy Maksymalna przepustowość teoretyczna 2 * częstotliwość * szerokość szyny / bity w gigabajtach Max Band = 2 x 1.1e9 x 64 / 1e9 = 140 GB / s

Dygresja: przepustowość efektywna Eff band = ( ( Br + Bw) / 1e9 ) / czas Br: bajty odczytane przez jądro Bw: bajty zapisane przez jądro 1e9: bity w gigabajcie czas: czas wykonania algorytmu Przykład: nbody N=32000 Br=32000+32000*32000 Bw=32000*2 Czas = 0.35 Efektywna przepustowość: 2,9 GBps

Za Best Programming Guide 3.2 GBps,

Efektywna przepustowość (nbody) optymalizacja G200 g80 Bez pamięci shared 1.79 GBps 0,55 GBps Z pamięcią shared 2.9 GBps 2,93 GBps Wnioski: g200 nie zwiększył bardzo przepustowości wydajnego algorytmu z pamięcią shared

Optymalizacje Rozwijanie pętli w kernelach (#pragma unroll ) device float2 accumulate_tile(float2 p, float2 f) { int i; #pragma unroll for(i=0; i < THREADS_PER_BLOCK; i++) f = force(shposition[i], p, f); } return f; Dzielenie (poj. precyzja) Zamiast / -> fdividef Pierwiastek Zamiast 1/sqrt -> rsqrtf() Więcej: http://developer.download.nvidia.com/compute/cuda/3_0/toolkit/docs/nvidia_cuda_programmingguide.pdf

Ćwiczenia points-cuda-gl-interop.zip Ściągnij Skompiluj i uruchom Zbadaj t(n) czas wykonania od liczby punktów Narysuj wykres t(n) Spróbuj zoptymalizować? nbody-nopt.zip Ściągnij Skompiluj i uruchom Zoptymalizuj (unroll, sqrt) Zbadaj t(n) czas wykonania od liczby punktów Narysuj wykresy t(n) w zależności od optymalizacji

Za tydzień Następny wykład 1.02.2011 Badanie wydajności w praktyce Cuda Thrust STL dla CUDA?