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

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

Programowanie kart graficznych

Programowanie kart graficznych

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

Programowanie Współbieżne

Programowanie procesorów graficznych w CUDA.

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

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

Wprowadzenie do programowania w środowisku CUDA. Środowisko CUDA

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

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

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

Programowanie CUDA informacje praktycznie i. Wersja

Programowanie aplikacji równoległych i rozproszonych

Obliczenia na GPU w technologii CUDA

Programowanie procesorów graficznych GPGPU

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

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

Programowanie CUDA informacje praktycznie i przykłady. Wersja

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

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

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

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

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

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

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

CUDA. cudniejsze przyk ady

Programowanie współbieżne i rozproszone

Struktura programu. Projekty złożone składają się zwykłe z różnych plików. Zawartość każdego pliku programista wyznacza zgodnie z jego przeznaczeniem.

Procesory kart graficznych i CUDA wer

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

Wstęp do Programowania, laboratorium 02

5 Przygotował: mgr inż. Maciej Lasota

CUDA ćwiczenia praktyczne

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

ISO/ANSI C - funkcje. Funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje

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

Procesory kart graficznych i CUDA

Wskaźniki. Informatyka

Procesory kart graficznych i CUDA wer PR

Przygotowanie kilku wersji kodu zgodnie z wymogami wersji zadania,

Programowanie w języku 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

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

Nowoczesne układy mikroprocesorowe EiT mgr 2011/2012

Język C zajęcia nr 11. Funkcje

GTX260 i CUDA wer

Procesory kart graficznych i CUDA wer

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

Tesla. Architektura Fermi

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

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 część 1. platforma GPGPU w obliczeniach naukowych. Maciej Matyka

Przetwarzanie Równoległe i Rozproszone

Podział programu na moduły

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

Język C++ zajęcia nr 2

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

PARADYGMATY PROGRAMOWANIA Wykład 4

Programowanie procesorów graficznych GPGPU

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

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

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

Linux Kernel III. Character devices

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

Zmienne, stałe i operatory

Argumenty wywołania programu, operacje na plikach

Uzupełnienie dot. przekazywania argumentów

Część 4 życie programu

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

1 Podstawy c++ w pigułce.

Lab 9 Podstawy Programowania

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

Programowanie w modelu przesyłania komunikatów specyfikacja MPI. Krzysztof Banaś Obliczenia równoległe 1

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

Programowanie proceduralne INP001210WL rok akademicki 2015/16 semestr letni. Wykład 6. Karol Tarnowski A-1 p.

main( ) main( void ) main( int argc, char argv[ ] ) int MAX ( int liczba_1, liczba_2, liczba_3 ) źle!

Programowanie procesorów graficznych GPU

Wprowadzenie do programowania w języku C

// Liczy srednie w wierszach i kolumnach tablicy "dwuwymiarowej" // Elementy tablicy są generowane losowo #include <stdio.h> #include <stdlib.

Podstawy algorytmiki i programowania - wykład 2 Tablice dwuwymiarowe cd Funkcje rekurencyjne

Szablony funkcji i szablony klas

Podstawy programowania. Wykład: 12. Struktury, unie, pola bitowe. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

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

1 Podstawy c++ w pigułce.

Język ludzki kod maszynowy

Wprowadzenie do szablonów szablony funkcji

Stałe, tablice dynamiczne i wielowymiarowe

Wprowadzenie do szablonów szablony funkcji

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

i3: internet - infrastruktury - innowacje

Klasy Obiekty Dziedziczenie i zaawansowane cechy Objective-C

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

PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO

Podstawy Programowania C++

Implementacja modelu FHP w technologii NVIDIA CUDA

TABLICE W JĘZYKU C/C++ typ_elementu nazwa_tablicy [wymiar_1][wymiar_2]... [wymiar_n] ;

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

Transkrypt:

Programowanie kart graficznych Architektura i API część 1

Literatura NVIDIA CUDA Programming Guide version 4.2 http//developer.download.nvidia.com/compute/devzone/ docs/html/c/doc/cuda_c_programming_guide.pdf NVIDIA CUDA Library Documentation http//developer.download.nvidia.com/compute/cuda/4_2/re l/toolkit/docs/online/index.html

CUDA model architektury język CUDA C

Kernel element języka CUDA C - rozszerzenie standardowego języka C/C++ stanowi specyficzny (składniowo i semantycznie) rodzaj funkcji wywołanie (aktywacja) kernela powoduje równoległe wykonanie jego treści (tekstu) w N równocześnie pracujących wątkach (gdzie N jest mniejsze równe liczbie dostępnych rdzeni) kernel definiowany jest poprzez użycie słowa kluczowego global

Kernel język CUDA C wprowadza specjalny element składniowy nazywany w oryginale mianem execution configuration element ten umieszcza się pomiędzy nazwą wywoływanego kernela i jego listą parametrów i ujmuje w parę nawiasów <<< i >>> np. Add<<<numBlocks, threadsperblock>>>(a, B, C); nazwa kernela execution configuration lista parametrów

Kernel każdy z wątków uruchomionych w ramach aktywacji kernela posiada własny, unikalny identyfikator (w oryginale threadid), który w treści kernela jest dostępny poprzez predefiniowaną zmienną threadidx zmienna threadidx jest strukturą

Przykład prostego kernela i jego aktywacji poniższy kod dodaje w sposób równoległy elementy dwóch wektorów A i B umieszczając wynik w wektorze C każdy z N wątków wykonuje dodawanie jednej pary elementów // definicja kernela global void VecAdd(float* A, float* B, float* C) { int i = threadidx.x; C[i] = A[i] + B[i]; int main() {... // wywołanie kernela z aktywacją N wątków VecAdd<<<1, N>>>(A, B, C); przykład nr 1

Hierarchia wątków zmienna threadidx jest strukturą (chociaż oryginalny podręcznik twierdzi, że jest wektorem) o trzech polach x, y i z takie podejście umożliwia identyfikowanie wątków pracujących (umownie!) w przestrzeni jedno, dwu lub trójwymiarowej przestrzeń taką można utożsamiać z liczbą wymiarów przetwarzanych agregatów danych (wektory, macierze, prostopadłościany) taką umowną przestrzeń obliczeń nazywa się w terminologii dokumentacji CUDA blokiem wątków (thread block)

Hierarchia wątków identyfikator wątku jest powiązany z jego indeksem przechowywanym w zmiennej threadidx w sposób następujący dla bloków jednowymiarowych identyfikator wątku jest wprost równy wartości threadidx.x

Hierarchia wątków dla bloków dwuwymiarowych o rozmiarach (Dx, Dy) identyfikator wątku jest równy threadidx.x + threadidx.y*dx dla bloków trójwymiarowych o rozmiarach (Dx, Dy, Dz) identyfikator wątku jest równy threadidx.x + threadidx.y*dx + threadidx.z*dx*dy

Przykład dwuwymiarowej przestrzeni wątków poniższy kod dodaje w sposób równoległy elementy dwóch macierzy A i B, umieszczając wynik w macierzy C każdy z N wątków wykonuje dodawanie jednej pary elementów // definicja kernela 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() {... // aktywacja kernela w bloku N*N*1 wątków int numblocks = 1; dim3 threadsperblock(n, N); MatAdd<<<numBlocks, threadsperblock>>>(a, B, C); przykład nr 2

Hierarchia wątków liczba równolegle (jednocześnie) pracujących wątków jest ograniczona z góry liczbą rdzeni udostępnianych przez sprzęt konkretnej karty CUDA łączny rozmiar wszystkich danych przetwarzanych przez wątek jest ograniczony z góry rozmiarem pamięci karty CUDA dostępnej w konkretnym przypadku nie znaczy to jednak, że oba powyższe parametry ograniczają z góry rozmiar problemu, jaki może być przetwarzany przez kartę treść kernela może być wielokrotnie (sekwencyjnie) wykonana w jednakowo uformowanych blokach w takim przypadku łączna liczba wątków jest równa iloczynowi liczby wątków w bloku i liczby bloków

Hierarchia wątków bloki wątków organizuje się w tzw. siatki bloków (w oryginale thread grids ) siatki bloków są jedno bądź dwuwymiarowe liczba bloków w siatce wynika zwykle z rozmiaru przetwarzanych danych lub liczby dostępnych rdzeni

Przykład dwuwymiarowej siatki wątków Źródło NVIDIA CUDA Programming Guide Version 3.0

Hierarchia wątków liczbę wątków w bloku oraz liczbę bloków w siatce specyfikuje się za pomocą execution configuration (składnia <<<... >>> ) wielkość rozmiaru bloku bądź siatki może być podana jako dana typu int (jak w pierwszym przykładzie) dana typu dim3 (jak w drugim przykładzie)

Hierarchia wątków każdy blok w siatce bloków jest identyfikowany przez jedno lub dwuwymiarowy indeks rozwiązanie to oparte jest na tej samym pomyśle, co identyfikator wątku i korzysta z tych samych mechanizmów identyfikator bloku jest przechowywany w predefiniowanej zmiennej (strukturze) o nazwie blockidx rozmiar bloku dostępny jest w predefiniowanej zmiennej (strukturze) o nazwie blockdim

Przykład użycia siatki bloków rozmiar bloku wątków (w celach demonstracyjnych) ustalono na 16x16 (razem 256 wątków) dla uproszczenia założono, że rozmiar macierzy (N) dzieli się bez reszty przez rozmiar bloku (16) // definicja kernela global void MatAdd(float A[N][N], float B[N][N], float C[N][N]) { int i = blockidx.x * blockdim.x + threadidx.x; int j = blockidx.y * blockdim.y + threadidx.y; if (i < N && j < N) C[i][j] = A[i][j] + B[i][j]; int main() {... // wywołanie kernela dim3 threadsperblock(16, 16); dim3 numblocks(n / threadsperblock.x, N / threadsperblock.y); MatAdd<<<numBlocks, threadsperblock>>>(a, B, C); przykład nr 3

Wymagania stawiane blokom wątków bloki muszą zostać skonstruowane w sposób biorący pod uwagę fakt, że pracują całkowicie niezależnie algorytm podziału problemu na bloki musi uwzględniać każdy z poniższych wariantów bloki wykonywane są sekwencyjnie bloki wykonywane są równolegle bloki wykonywane są seriami (równolegle w serii, serie wykonywane sekwencyjnie) algorytm podziału nie może zakładać, że bloki wykonywane są w jakiejkolwiek znanej z góry kolejności tylko spełnienie tych warunków gwarantuje, że uzyskany kod będzie w pełni skalowalny

Bloki wątków wątki pracujące w ramach jednego bloku mogą organizować wzajemną współpracę poprzez wymianę danych z użyciem pamięci współdzielonej (dostępnej dla wszystkich wątków) synchronizując wzajemnie swoje wykonanie synchronizacja wątków jest możliwa w tzw. punktach synchronizacji (w oryginale synchronization points) tworzonych poprzez wywołania funkcji syncthreads() wg zapewnień zawartych w dokumentacji szybkość pracy pamięci współdzielonej jest porównywalna z szybkością cache'a L1 funkcja syncthreads() jest implementowana sprzętowo i koszt jej wywołania jest minimalny

Hierarchia pamięci pracujące wątki mają dostęp do danych przechowywanych w różnych przestrzeniach pamięci urządzenia CUDA każdy wątek może używać niewielkiej własnej (prywatnej) pamięci lokalnej używanej do przechowywania zmiennych zadeklarowanych lokalnie w ciele kernela; pamięc ta jest w pełni izolowana każdy blok wątków może używać bloku pamięci współdzielonej widocznej dla wszystkich wątków w bloku; czas życia tej pamięci jest tożsamy z czasem życia bloku wszystkie bloki wątków mają dostęp do pamięci globalnej

Hierarchia pamięci dodatkowo karta CUDA zawiera dwa dodatkowe, specjalizowane bloki pamięci (z punktu widzenia wątków jest to pamięć tylko do odczytu) pamięć stałych pamięć tekstur Zawartość pamięci globalnej, stałych i tekstur może być traktowana jako nieulotna (także pomiędzy odpaleniami kerneli, jeśli tylko pochodzą z jednej i tej samej aplikacji)

Kompilator nvcc

Środowisko pracy kompilatora.ptx.cu nvcc host binary code a.out ptx byte code

Środowisko uruchomienia kodu a.out host binary code ptx byte code JIT compiler CPU host memory device memory GPU

CUDA API

CUDA API rozpoznawanie cech środowiska pobranie informacji o liczbie dostępnych kart CUDA cudaerror_t cudagetdevicecount (int *count) parametr count wskaźnik na daną typu int, w której funkcja umieści daną informującą ile urządzeń CUDA jest dostępnych w systemie wynik cudasuccess poprawne zakończenie działania funkcji

cudagetdevicecount() - przykład użycia int devcnt; cudagetdevicecount(&devcnt); if(devcnt == 0) puts("no CUDA devices available exiting.");

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { int canmaphostmemory; Pole podaje informację, czy dane urządzenie realizuje funkcjonalności udostępniane przez funkcje cudahostalloc() i cudahostgetdevicepointer()

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { int clockrate; Pole podaje informację o częstotliwości zegara danej karty CUDA (częstotliwość wyrażona jest w kilohercach)

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { int computemode; Pole podaje informację o akceptowanym przez daną kartę trybie obliczeń cudacomputemodedefault - tryb domyślny (dla tego urządzenia więcej niż jeden wątek może użyć funkcji cudasetdevice()). cudacomputemodeexclusive - tryb wyłączny (dla tego urządzenia tylko jeden wątek może użyć funkcji cudasetdevice()). cudacomputemodeprohibited tryb chroniony (żaden wątek nie może użyć funkcji cudasetdevice() dla tego urządzenia).

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { int deviceoverlap; Pole podaje informację o tym, czy dany sprzęt urządzenia CUDA potrafi w tym samym czasie przemieszczać (kopiować) bloki pamięci i wykonywać kod kerneli.

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { int integrated; Pole podaje informację o tym, czy dane urządzenie CUDA jest wbudowane czy dołączone.

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { int kernelexectimeoutenabled; Pole podaje informację o tym, czy dane urządzenie CUDA narzuca limit czasu nieprzerwanej pracy kodu kernela.

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { int major; Numer wersji CC (Computer Capability) część ważniejsza (przed kropką).

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { int maxgridsize[3]; Maksymalny, akceptowany przed dane urządzenie, rozmiar każdego z trzech wymiarów siatki.

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { int maxthreadsdim[3]; Maksymalny, akceptowany przed dane urządzenie, rozmiar każdego z trzech wymiarów bloku.

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { int maxthreadsperblock; Maksymalna, akceptowana przed dane urządzenie, liczba wątków w bloku.

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { int mempitch; Maksymalna, akceptowana przed dane urządzenie, wyrażona w bajtach wielkość boiska (pitch), które może podlegać jednorazowemu kopiowaniu.

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { int minor; Numer wersji CC (Computer Capability) część pośledniejsza (za kropką).

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { int multiprocessorcount; Liczba rdzeni zabudowanych w architekturze danego urządzenia CUDA.

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { char name[256]; Nazwa handlowa danego urządzenia CUDA (ASCIIZ).

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { int regsperblock; Liczba 32 bitowych rejestrów dostępnych w danym urządzeniu CUDA dla każdego pracującego bloku wątków.

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { size_t sharedmemperblock; Rozmiar (w bajtach) pamięci dzielonej dostępnej w danym urządzeniu CUDA dla każdego pracującego bloku wątków.

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { size_t texturealignment; Rozmiar (w bajtach) dopasowania tekstur w danym urządzeniu CUDA.

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { size_t totalconstmem; Rozmiar (w bajtach) pamięci stałych w danym urządzeniu CUDA.

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { size_t totalglobalmem; Rozmiar (w bajtach) pamięci globalnej w danym urządzeniu CUDA.

CUDA API rozpoznawanie cech środowiska reprezentowanie informacji o środowisku struct cudadeviceprop { int warpsize; Optymalny rozmiar osnowy wątków (temat ten omówimy przy najbliższej nadarzającej się okazji).

CudaDeviceProp faktyczna deklaracja struct cudadeviceprop { char name[256]; size_t totalglobalmem; size_t sharedmemperblock; int regsperblock; int warpsize; size_t mempitch; int maxthreadsperblock; int maxthreadsdim[3]; int maxgridsize[3]; size_t totalconstmem; int major; int minor; int clockrate; size_t texturealignment; int deviceoverlap; int multiprocessorcount; int kernelexectimeoutenabled; int integrated; int canmaphostmemory; int computemode;

CUDA API rozpoznawanie cech środowiska pobranie informacji o środowisku cudaerror_t cudagetdeviceproperties( struct cudadeviceprop *prop, int device) parametry prop wskaźnik na strukturę, w której funkcja umieści efekt swojego działania device numer urządzenia, którego cechy mają zostać rozpoznane (pierwsza karta ma numer 0) wynik cudasuccess poprawne zakończenie działania funkcji cudaerrormemoryallocation błąd przydziału, awaryjny powrót z funkcji

CUDA API elementarne zarządzanie pamięcią przydzielenie bloku pamięci urządzenia cudaerror_t cudamalloc(void **devptr,size_t size) parametry devptr wskaźnik na wskaźnik reprezentujący przydzielony blok pamięci size rozmiar żądanego bloku pamięci (w bajtach) wynik cudasuccess poprawne zakończenie działania funkcji cudaerrormemoryallocation błąd przydziału, awaryjny powrót z funkcji

CUDA API elementarne zarządzanie pamięcią zwolnienie bloku pamięci urządzenia cudaerror_t cudafree(void *devptr) parametry devptr wskaźnik na blok pamięci przydzielony wcześniej funkcją cudamalloc() lub cudamallocpitch() wynik cudasuccess poprawne zakończenie działania funkcji cudainvaliddevicepointer niepoprawna wartość wskaźnika devptr

CUDA API elementarne zarządzanie pamięcią kopiowanie bloku pamięci z/do urządzenia cudaerror_t cudamemcpy( void *dst, const void *src, size_t count, enum cudamemcpykind kind)

Parametry dst wskaźnik na docelowy blok pamięci (hosta lub urządzenia) src wskaźnik na źródłowy blok pamięci (urządzenia lub hosta) count rozmiar kopiowanego bloku pamięci (w bajtach) kind kierunek kopiowania - jeden z cudamemcpyhosttohost (host host) cudamemcpyhosttodevice (host karta) cudamemcpydevicetohost (karta host) cudamemcpydevicetodevice (karta karta)

Wynik cudasuccess poprawne zakończenie działania funkcji możliwe sytuacje błędów cudaerrorinvalidvalue, cudainvaliddevicepointer, cudaerrorinvaliddevicepointer, cudaerrorinvalidmemcpydirection

Kompletny program doświadczalny - część 1/2 #include <stdio.h> #define N 1024 #define BLOCK_SIZE 16 float float int harray[n]; * darray; blocks; void prologue(void) { for(int i = 0; i < N; i++) { harray[i] = i + 1; cudamalloc((void**)&darray, sizeof(harray)); cudamemcpy(darray, harray, sizeof(harray),cudamemcpyhosttodevice); void epilogue(void) { cudamemcpy(harray, darray, sizeof(harray), cudamemcpydevicetohost); cudafree(darray);

Kompletny program doświadczalny - część 2/2 global void sqr(float *A) { int x = blockdim.x * blockidx.x + threadidx.x; if(x < N) A[x] = A[x] * A[x]; int main(int argc, char** argv) { int devcnt; cudagetdevicecount(&devcnt); if(devcnt == 0) { perror("no CUDA devices available -- exiting."); return 1; prologue(); blocks = N / BLOCK_SIZE; if(n % BLOCK_SIZE) blocks++; sqr<<<blocks, BLOCK_SIZE>>>(dArray); cudathreadsynchronize(); epilogue(); return 0;