OpenCL tutorial – część 3 – sumowanie wektorów

W kolejnej części wprowadzenia do OpenCL wykonamy i uruchomimy pierwszy program na GPU. Zadaniem programu będzie sumowanie dwóch wektorów.

Przykładowy kod w C++ dla takiej operacji może wyglądać tak:

Pobieramy kod z poprzedniej części kursu.

Na początku utworzymy tablice przechowujące wektory:

Zmienna „vectorNumber” przechowuje rozmiar wektora. Funkcja „randomizeArray” wypełnia tablice losowymi wartościami. Jej kod zostanie przedstawiony później.

Pierwszą czynnością, którą musimy wykonać jest utworzenie kontekstu, który umożliwi nam wykonywanie poleceń na danym urządzeniu.

Następnie tworzymy kolejkę poleceń na wybranym przez nas urządzeniu:

Alokujemy pamięć na karcie graficznej dla naszych wektorów. Tworzymy dwa bufory tylko do odczytu, które będą przechowywać wektory A i B oraz jeden tylko do zapisu, do którego zostanie zapisany wynik sumowania:

Teraz czas na program w OpenCL. Program w C++ wykonuje sumowanie liczb sekwencyjnie. Najpierw sumuje pierwszą liczbę z wektora A z pierwszą liczbą z wektora B, następnie drugą liczbę z wektora A z drugą liczbą z wektora B itd.

Możemy łatwo zauważyć, że sumowanie pierwszych liczb nie jest w żaden sposób zależne od sumowania drugich liczb. Zamiast wykonywania tych operacji jedna po drugiej, możemy wykonać je równocześnie, co w żaden sposób nie wpłynie na  wynik końcowy.

Poniższy program wykona sumowanie tylko dwóch liczb, a nie całego wektora. Skąd program wie, które liczby ma sumować? Funkcja „get_global_id” zwraca pewien unikalny identyfikator, na chwilę obecną możemy przyjąć, że to rozmiar wektora, który zdefiniowaliśmy w zmiennej „vectorSize”.

Umieszczamy poniższy kod w pliku „Add.cl”:

Wczytujemy kod programu z pliku, ładujemy go do GPU i kompilujemy:

Tworzymy kernel i przekazujemy do niego argumenty. Kernel to funkcja zdefiniowana w kodzie programu, który właśnie załadowaliśmy na GPU:

Program jest gotowe, więc możemy przystąpić do wczytania wcześniej przygotowanych danych do GPU i uruchomienia kernela:

Funkcja „clEnqueueWriteBuffer” kopiuje dane z hosta (czyli naszego programu napisanego w C++) do GPU, a funkcja „clEnqueueReadBuffer” wykonuje operację odwrotną, czyli kopiuje dane z GPU do hosta.

Funckja „clEnqueueNDRangeKernel” uruchamia kernel. Jako piąty argument przekazujemy rozmiar wektóych, które sumujemy. Kernel zostanie uruchomiony tyle razy, ile wynosi wartość zmiennej „vectorSize”.

Teraz wracamy do kodu kernela i funkcji „get_global_id”. Jeżeli rozmiar wektora (vectorSize) to 32, to funkcja „get_global_id” w pierwszym uruchomionym kernelu zwróci 0, w drugim – 1, w trzecim – 2 itd. Dzięki temu jesteśmy w stanie określić które liczby z wektorów powinien sumować kernel.

Wyniki sumowania będą dostępne w zmiennej „c”. Zobaczmy czy operacja powiodła się:

Pamiętamy, aby na koniec posprzątać po sobie i zwolnić pamięć:

Kod programu

Kod całego programu powinien wyglądać tak:

Źródła w serwisie GitLab.

W następnej części kursu poznamy API dla języka C++.

2 Comments on “OpenCL tutorial – część 3 – sumowanie wektorów

  1. Hm, u mnie niby wszystko ładnie się kompiluje, ale sumowanie wektorów nie działa, tablica c na koniec działania programu jest cała wypełniona zerami.

Dodaj komentarz

Twój adres email nie zostanie opublikowany.