Programowanie procesorów graficznych w CUDA.

Podobne dokumenty
Programowanie kart graficznych

Programowanie Współbieżne

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

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

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

Wprowadzenie do programowania w środowisku CUDA. Środowisko CUDA

Programowanie współbieżne i rozproszone

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

Wstęp do Programowania 2

1 Pierwsze kroki w C++ cz.3 2 Obsługa plików

Obliczenia na GPU w technologii CUDA

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

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

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

Wprowadzenie do OpenMP

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

CUDA ćwiczenia praktyczne

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

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

Programowanie CUDA informacje praktycznie i. Wersja

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

Zajęcia nr 1 Podstawy programowania. dr inż. Łukasz Graczykowski mgr inż. Leszek Kosarzewski Wydział Fizyki Politechniki Warszawskiej

Programowanie CUDA informacje praktycznie i przykłady. Wersja

Procesory kart graficznych i CUDA wer

Projektowanie klas c.d. Projektowanie klas przykład

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

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

Technologie cyfrowe semestr letni 2018/2019

Wprowadzenie do GPGPU

Prof. Danuta Makowiec Instytut Fizyki Teoretycznej i Astrofizyki pok. 353, tel danuta.makowiec at gmail.com

Programowanie obiektowe W3

I - Microsoft Visual Studio C++

typ y y p y z łoż o on o e n - tab a lice c e w iel e owym m ar a o r we, e stru r kt k ury

Programowanie - wykład 4

MACIERZE. Sobiesiak Łukasz Wilczyńska Małgorzata

Operacje wejścia/wyjścia (odsłona druga) - pliki

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

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

Programowanie w językach

C++ wprowadzanie zmiennych

Programowanie kart graficznych

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

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

Programowanie obiektowe w C++ Wykład 1

Alokacja pamięci dla tablicy dwuwymiarowej

wykład IV uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C, a C++. wykład IV dr Jarosław Mederski Spis Język C++ - wstęp

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

tablica: dane_liczbowe

Część 4 życie programu

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

Programowanie procesorów graficznych GPGPU

Wstęp do Informatyki

Pytania sprawdzające wiedzę z programowania C++

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

1. Wprowadzenie do C/C++

Programowanie w języku C++

Aby uzyskać zaliczenie w pierwszym terminie (do 30 stycznia 2018) rozliczyć trzeba co najmniej 8 projektów, po 4 z każdej z części: C++ oraz Python.

Programowanie Procedurale

Zaawansowane programowanie w języku C++ Biblioteka standardowa

Procesory kart graficznych i CUDA wer PR

Wprowadzenie do GPGPU

GTX260 i CUDA wer

Programowanie Obiektowo Zorientowane w języku c++ Przestrzenie nazw

Programowanie aplikacji równoległych i rozproszonych

r. Tablice podstawowe operacje na tablicach

Procesory kart graficznych i CUDA wer

Tablice. Monika Wrzosek (IM UG) Podstawy Programowania 96 / 119

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

Algorytmika i programowanie. Wykład 2 inż. Barbara Fryc Wyższa Szkoła Informatyki i Zarządzania w Rzeszowie

Wykład II. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Wykład I. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

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

Zajęcia nr 2 Programowanie strukturalne. dr inż. Łukasz Graczykowski mgr inż. Leszek Kosarzewski Wydział Fizyki Politechniki Warszawskiej

Podstawy Informatyki. Inżynieria Ciepła, I rok. Wykład 10 Kurs C++

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

Wstęp do programowania

DYNAMICZNE PRZYDZIELANIE PAMIECI

Szablon klasy std::vector

Programowanie i struktury danych

Procesory kart graficznych i CUDA

Informacje wstępne #include <nazwa> - derektywa procesora umożliwiająca włączenie do programu pliku o podanej nazwie. Typy danych: char, signed char

1 Wskaźniki. 1.1 Główne zastosowania wskaźników

Globalne / Lokalne. Wykład 15. Podstawy programowania (język C) Zmienne globalne / lokalne (1) Zmienne globalne / lokalne (2)

Jak Windows zarządza pamięcią?

Podstawy algorytmiki i programowania - wykład 5 C-struktury cd.

Operacje wejścia/wyjścia odsłona pierwsza

Wstęp do programowania

Wstęp do OpenCL. Czyli jak wykorzystać moc drzemiącą w GPU. Marek Zając 2013r. zajacmarek.com

Jzyk C++ cz 3. Jarosław Gramacki Instytut Informatyki i Elektroniki ( $)*)+' *, - ( ' )*'.' '',*/ *, ','*0) 1 / ) %*+ 2'' 2" ( $%%) )'20 )*0) 1 / )

1. Wprowadzenie do C/C++

Wprowadzenie do programowania w środowisku CUDA. Środowisko CUDA

1 Wskaźniki i zmienne dynamiczne, instrukcja przed zajęciami

Język C++ wykład VIII

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

public: // interfejs private: // implementacja // składowe klasy protected: // póki nie będziemy dziedziczyć, // to pole nas nie interesuje

Plan. krótkie opisy modułów. 1 Uwagi na temat wydajności CPython a. 2 Podstawowe techniki poprawiające wydajność obliczeniową

Wykład. Materiały bazują częściowo na slajdach Marata Dukhana

Programowanie obiektowe i C++ dla matematyków

Funkcja (podprogram) void

Podstawy Programowania

Transkrypt:

Programowanie procesorów graficznych w CUDA. Kompilujemy program Alokacja zasobów gpgpu oraz załadowanie modułu CUDA odbywa się za pomocą komend: qsub -q gpgpu -I -l walltime=2:00:00,nodes=1:ppn=1:gpus=1 module add gpu/cuda Kompilacji programów dokonujemy za pomocą komendy nvcc, obsługującej przemieszane kody C/C++ i CUDA (te ostatnie często, choć nie zawsze zapisywane w plikach z rozszerzeniem.cu). Proszę obejrzeć parametry wywołania kompilatora, np. za pomocą nvcc help, lub w podobny sposób. Sugerowane parametry kompilacji: -gencode arch=compute_20,code=sm_20. Odczytanie parametrów karty #include<builtin_types.h> #include "cuda_runtime.h" #include "device_launch_parameters.h" #include <iostream> #include <fstream> #include <stdio.h> #include <math.h> #include <vector> #include <time.h> using namespace std; void printdevprop(cudadeviceprop devprop){ const int kb = 1024; const int mb = kb*kb; cout << "Cuda vesion :" << CUDART_VERSION << endl; cout << "Name :" << devprop.name << endl; cout << "Total global memory :" << devprop.totalglobalmem / mb << "MB" << endl; cout << "Total shared memory :" << devprop.sharedmemperblock / kb << "KB" << endl; cout << "Total register per block :" << devprop.regsperblock << endl; cout << "Total warp size :" << devprop.warpsize << endl; cout << "Max memory pitch :" << devprop.mempitch << endl; cout << "Max threads per block :" << devprop.maxthreadsperblock << endl; for( int i = 0; i < 3; ++i) cout << "Max dimension of block :" << devprop.maxthreadsdim[i] << endl;

for(int i = 0; i < 3; ++i) cout << "Max dimension of grid :" << devprop.maxthreadsdim[i] << endl; cout << "Clock rate :" << devprop.clockrate << endl; cout << "Total const memory :" << devprop.totalconstmem / kb << endl; cout << "Number of multiprocessors :" << devprop.multiprocessorcount << endl; int main() { int devcnt; cudastatus = cudagetdevicecount(&devcnt); //sprawdznie czy istnieją urządzenia cuda w systemie if(cudastatus!= cudasuccess) fprintf(stderr, "cuda GetDivevie Count failed!!"); else cout << "There are" << devcnt << " CUDA devices." << endl; for(int i = 0; i < devcnt; ++i){ cudadeviceprop devprop; cudagetdeviceproperties(&devprop, i); printdevprop(devprop); cout << "Print to eny key to exit..." << endl; char c; cin >> c; return 0; Program odczytuje podstawowe parametry zainstalowanego GPU. Proszę uruchomić program, a następnie przeczytać i przeanalizować wyniki - będą przydatne przy kolejnych programach. Za podstawowe parametry możemy uznać: 1. Liczba multiprocesorów 2. Taktowanie multiprocesorów oraz pamięci 3. Szerokość szyny danych 4. Wielkość pamieci RAM 5. Rodzaj pamięci 6. Maksymalne ilości wątków oraz bloków. Pierwszy kernel + pomiar czasu Proszę zapoznać się z poniższymi funkcjami. Alokacja oraz kopiowanie danych :

cudamalloc((void **) &a_d, size); // alokuj pamięć na GPU cudamemcpy(a_d, a_h, size, cudamemcpyhosttodevice);//kopiuj dane na GPU Pomiaru czasu na GPU dokonujemy za pomocą funkcji opartych na zdarzeniach : cudaevent_t start, stop; cudaprintfinit(); cudaeventcreate(&start); cudaeventcreate(&stop); cudaeventrecord(start, 0); wykonaj obliczenia na GPU: kernel <<< n_blocks, block_size >>> (a_d, N); cudaeventsynchronize(stop); float time; cudaeventelapsedtime(&time, start, stop); cout << "Czas wykonania programu GPU: " << time << endl; cudaeventdestroy(starthtd); cudaeventdestroy(stophtd); prześlij wyniki cudamemcpy(a_h, a_d, sizeof(float)*n, cudamemcpydevicetohost); cudafree(a_d); Proszę uruchomić program : #include<builtin_types.h> #include "cuda_runtime.h" #include "device_launch_parameters.h" #include <iostream> #include "cuprintf.cu" #define N 16 int Array[N]; int *devarray; int blocks; void allocatememoryandcopydatatodevice(void){ for(int i = 0; i < N; i++){ Array[i] = i; cudastatus = cudamalloc((void**)&devarray, sizeof(array)); std::cerr << "cudamemcpy host to device failed!\n"; cudastatus = cudamemcpy(devarray, Array, sizeof(array), cudamemcpyhosttodevice);

std::cerr << "cudamemcpy failed!\n"; void copydatatohost(void){ cudastatus = cudamemcpy(array, devarray, sizeof(array),cudamemcpydevicetohost); std::cerr << "cudamemcpy device to host failed!\n"; cudafree(devarray); global void showdataindevice(int *A){ if(threadidx.x == 0){ for(int i = 0; i < N; i++) cuprintf("data in device : %d \n", A[i]); int main() { cudadeviceprop prop; int count; cudastatus = cudagetdevicecount(&count); if(cudastatus!= cudasuccess) { std::cerr << "cudagetdevicecount failed, bailing out\n"; cudastatus = cudagetdeviceproperties(&prop,0); if (cudastatus!= cudasuccess){ std::cerr << "cudagetdeviceproperties failed, bailing out\n"; cudaprintfinit(); allocatememoryandcopydatatodevice(); showdataindevice<<<1,1>>>(devarray); cudaprintfdisplay(stdout, true); cudaprintfend(); cudathreadsynchronize(); copydatatohost(); return 0; Następnie proszę zmienić liczbę bloków oraz liczbę wątków w bloku(pierwszy i drugi parametr wywołania kernela<<>> ). W programie została zastosowana funkcja cuprintf(). Dzięki niej możemy wyświetlić wyniki prac danego wątku. Aby było możliwe jej użycie należy do folderu w którym znajdują się nasze programy skopiować cuprintf.cu oraz cuprintf.cuh.

Dodawanie wektorów Proszę uruchomić program dodawania wektorów na GPU i CPU napisany według poniższego schematu. #include<builtin_types.h> #include "cuda_runtime.h" #include "device_launch_parameters.h" #include "cuprintf.cu" #include <iostream> #define N 16 #define NumberOfThreads 4 int A[N]; int B[N]; int C[N] = {0; int *deva; int *devb; int *devc; int blocks; void alocatememoryandcopydatatodevice(void){ for(int i = 0; i < N; i++){ A[i] = i; B[i] = i*i; cudastatus = cudamalloc((void**)&deva, sizeof(a)); std::cerr << "cudamalloc failed!\n"; cudastatus = cudamalloc((void**)&devb, sizeof(b)); std::cerr << "cudamalloc failed!\n"; cudastatus = cudamalloc((void**)&devc, sizeof(c)); std::cerr << "cudamalloc failed!\n"; cudastatus = cudamemcpy(deva, A, sizeof(a), cudamemcpyhosttodevice); std::cerr << "cudamemcpy host to device failed!\n"; cudastatus = cudamemcpy(devb, B, sizeof(b), cudamemcpyhosttodevice); std::cerr << "cudamemcpy host to device failed!\n"; void copydatatohost(void){ cudastatus = cudamemcpy(c, devc, sizeof(c),cudamemcpydevicetohost);

std::cerr << "cudamemcpy device to host failed!\n"; cudafree(deva); cudafree(devb); cudafree(devc); global void AddKernelInSharedMemory(int *A, int *B, int *C){ shared int SharedMemoryA[N]; shared int SharedMemoryB[N]; shared int SharedMemoryC[N]; unsigned int tid = threadidx.x + blockidx.x*blockdim.x; //copy data to shared memory SharedMemoryA[threadIdx.x] = A[tid]; SharedMemoryB[threadIdx.x] = B[tid]; SharedMemoryC[threadIdx.x] = SharedMemoryA[threadIdx.x] + SharedMemoryB[threadIdx.x]; syncthreads(); //copy result to global memory C[tid] = SharedMemoryC[threadIdx.x]; int main() { int no_devices; //check device status cudastatus = cudagetdevicecount(&no_devices); if(cudastatus!= cudasuccess) { std::cerr << "cudagetdevicecount failed, bailing out\n"; cudadeviceprop props; cudastatus = cudagetdeviceproperties(&props,0); if(cudastatus!= cudasuccess) { std::cerr << "cudagetdeviceproperties failed, bailing out\n"; cudaprintfinit(); blocks = N/NumberOfThreads; alocatememoryandcopydatatodevice(); AddKernelInSharedMemory<<<blocks,NumberOfThreads>>>(devA,devB,devC); cudaprintfdisplay(stdout, true); cudaprintfend(); cudathreadsynchronize(); copydatatohost(); std::cout << "Result:\n"; for(int i = 0; i < N; i ++) { std::cout << A[i] << "+" << B[i] << "=" << C[i] << std::endl; return 0;

Proszę uzupełnić kod o pomiar czasu, a następnie uruchomić go próbując różne rozmiary tablicy, różne liczby wątków i bloków. Proszę też zwrócić uwagę na ograniczenia na maksymalną liczbę wątków w bloku. W szczególności proszę: 1. Umożliwić ustalanie rozmiarów tablicy z klawiatury w trakcie wykonania, tak żeby łatwo było zebrać wyniki dla różnych danych; 2. Dodać kod, który wykonuje dodawanie tylko na CPU z użyciem OpenMP który podaje czas wykonania - tak żeby można było porównać GPU z CPU. 3. Umożliwić zmianę struktury bloków (ile wątków na blok?) i gridów (ile bloków w gridzie?). Proszę ocenić jak wpływa to efektywność programu.