OpenCL, CUDA, etc.

0

Witam

Szukam informacji na temat technologii takich jak OpenCL, CUDA, itd.

Muszę przeprowadzić pewne bardzo czasochłonne obliczenia. Obliczenia dobrze
się zrównoleglają, więc wybór padł karty graficzne. Nie wiem jakie karty graficzne
zakupić i jaką technologią programowania się posłużyć. Mam pewne doświadczenie w
programowaniu i w optymalizowaniu programów na CPU, ale nigdy nic nie
napisałem na GPU, nawet hello world.

Z kart graficznych ciekawy stosunek ceny do wydajności mają nowe kartu ma
układzie NVIDI 16XX, np. 1650, 1660, 1660TI. Karta Radeon RX 460 też
wydaje się wydajna i tania, ale ma tylko 2GB pamięci.

Czy w sieci można znaleźć kilka przykładowych (najlepiej minimalnych) problemów
rozwiązanych na wiele sposobów w celu porównania? Ten sam problem
można rozwiązać w Javie na CPU, w C++ na CPU (z wykorzystaniem np.
długich rejestrów), ostatecznie w OpenCL, w CUDA i porównać czasy wykonania
a najlepiej także zużycie energii.

Z góry dziękuję za wszelką pomoc.

2

Z materiałów:

  • materiały np. MIMUW - na pewno coś jest
  • dokumentacja nVidii (CUDA)
  • dokumentacja OpenCL

Nie wiem na jakim poziomie skomplikowania chcesz te przykłady, ale co do OpenCL powinienem mieć coś zakopanego na jakimś dysku Google z zajęć z zeszłego roku. Takie jakieś proste przypadki w stylu przekształcenia na macierzach i wektorach, jakieś mnożenie macierz-macierz czy macierz-wektor jako kernele OpenCL, jakieś proste optymalizacje, choć raczej lepsze lub gorsze - jak chcesz, mogę spróbować je odszukać i podrzucić odnośnik.

Jakieś zalążki kodu do dokończenia/zmodyfikowania na których mógłbyś poćwiczyć znajdziesz gdzieś w odmętach materiałów do laboratorium z rozprochów i HPC

Choć jeśli mam być szczery, to jeśli i tak nigdy niczego nie robiłeś czegoś takiego, to prawdopodobnie lepiej wyjdziesz na zaprzągnięciu do roboty jakiejś biblioteki z języka wyższego poziomu (języka, w którym masz już działający kod na CPU?), która pod spodem sama zaprzęgnie do roboty GPU za pośrednictwem czy to OpenCL, czy czegokolwiek - GPU rządzi się trochę innymi prawami niż CPU, do tego stopnia, że to, co na CPU jest optymalizacją, na GPU potrafi zabić wydajność i odwrotnie ;)

A, no i zanim utopisz kasę w kartach graficznych, to lepiej popróbuj na tym, co masz, bo może się okazać, że np. wydajność wersji na GPU zostanie ubita przez częste wymiany danych między pamięcią RAM a pamięcią RAM karty. Magistrala potrafi być strasznym bottleneckiem - co z tego, że kod się dobrze zrównolegla i wyciśniesz np. 3TFlops z GPU vs np. 250GFlops z CPU, skoro 99% czasu zejdzie na I/O ;)

1

Zamiast babrać się bezpośrednio na niskim poziomie najlepiej oddeleguj to do jakiejś biblioteki. Nie wiem w czym piszesz, jeśli C++ to rozważ https://github.com/boostorg/compute

4

Na GPU dobrze robi się obliczenia bazujące na masie danych - symulacje ruchu cząsteczek, gazów, płynów, sieci neuronowe, przetwarzanie obrazów - tam gdzie jeden i ten sam kod może pracować na setkach czy tysiącach danych równolegle.

Jak wspomniano wyżej do niektórych problemów są już znane biblioteki wysokiego poziomu korzystające z GPU i nie trzeba się tego niskopoziomowego kodowania uczyć (TensorFlow, Keras). Pytanie co chcesz za obliczenia robić?

Na GPU masz jeszcze standard OpenACC, ale coś mało o nim słyszę.

Na CPU masz dodatkowo:

Proponowałbym zacząć od Threadrippera i OpenMP bo jest to chyba najpopularniejsze, najtańsze i najprostsze rozwiązanie jeśli chcesz coś programować równolegle od zera.
W drugiej kolejności OpenACC gdyż pozwala na wykorzystanie GPU przy podobnym do OpenMP podejściu.
Oba podejścia to raczej C/C++/Fortran.

W Javie to albo wspomniane wcześniej OpenCL/CUDA albo https://www.coursera.org/learn/parallel-programming-in-java

0

superdurszlak napisał
Z materiałów:
materiały np. MIMUW - na pewno coś jest
dokumentacja nVidii (CUDA)
dokumentacja OpenCL

Dziękuję, będę za jakiś czas się przekopywał przez to :)

Nie wiem na jakim poziomie skomplikowania chcesz te przykłady,

Przykłady bym chciał klasyczne, znane, najprostsze, minimalne, różnorodne.
Przykładowo:

  1. Mnożenie macierzy, różne rozmiary macierzy, różne typy, różna ilość
    transferów. Np. mnożymy miliardy razy jedną i samą małą parę macierzy, czyli
    wszystkie dane mieszczą się w pamięci GPU. Robimy to Javie na CPU, w C++ na
    CPU (z użyciem SIMD), w OpenCL na CPU i na GPU, w CUDA z biblioteki na CPU i w
    CUDA napisanym adhoc na kolanie. Potem celowo raz na ileś mnożeń robimy
    transfer do karty, no a do CPU nie trzeba bo dane z RAM są dostępne dla CPU.
  2. Potem może jakiś problem kombinatoryczny, np. problem skoczka szachowego, albo
    problem komiwojażera metodą burut-force. Chciałbym zobaczyć jakie w praktyce
    są różnice w czasach wykonania pomiędzy dobrą a przeciętną implementacją i
    pomiędzy CPU, GPU, OpenCL i CUDA.
  3. Rozkłąd na czynniki pierwsze.
  4. Dowodzenie twierdzeń logicznych.

Wszystko oczywiscie tym samym algorytmem w każdym sprzęcie. Mogą być przykłady
inne, byle były ogólnie znane i proste, aby łatwo wyrabiały pogląd.

Choć jeśli mam być szczery, to jeśli i tak nigdy niczego nie robiłeś czegoś takiego,

Robiłem, ale na CPU, z uwzględnieniem wątków, rozszerzeń procesora, wstawek asemblerowych.

to prawdopodobnie lepiej wyjdziesz na zaprzągnięciu do roboty jakiejś biblioteki

Nie ma do tego bibliotek, muszę zrobić sam... albo odpuścić jak uznam że będzie
zbyt ciężko lub zbyt drogo.

języka wyższego poziomu (języka, w którym masz już działający kod na CPU?),

Jakieś minimalne fragmenty które może nadawawałyby się do testow mam w C++ na CPU, ale
chyba nie można tego łatwo do OpenCL przerzucić? Chyba trzeba na nowo napisać?

GPU rządzi się trochę innymi prawami niż CPU, do tego stopnia, że to, co na CPU jest
optymalizacją, na GPU potrafi zabić wydajność i odwrotnie ;)

Tak, to nie jest zaskoczeniem dla mnie.

A, no i zanim utopisz kasę w kartach graficznych, to lepiej popróbuj na tym, co masz, bo
może się okazać, że np. wydajność wersji na GPU zostanie ubita przez częste wymiany danych
między pamięcią RAM a pamięcią RAM karty.

Powiedzmy na potrzeby rozmowy, że komunikacja pomiędzy GPU a pamiecią RAM będzie rzadko,
np. raz na kilka minut.

Pozdrawiam

1

Jeśli chodzi o rozwiązanie sprzętowe, to może kup najtańszą kartę do przygotowania rozwiązania, a docelowo odpal to na maszynach w AWS np.
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/accelerated-computing-instances.html#gpu-instance-families
https://aws.amazon.com/marketplace/pp/NVIDIA-NVIDIA-CUDA-Toolkit-75-on-Amazon-Linux/B01LZMLK1K

Tylko zrób to szybko, bo płacisz za czas. :) Nie wiem jaka jest perspektywa czasowa tego zadania, ale jeśli ma to być jednorazowa akcja, to chyba nie ma sensu wrzucać kasy w sprzęt, który wykorzystasz raz (no chyba, że jesteś graczem ;)).

0
robertos7778 napisał(a):

Jeśli chodzi o rozwiązanie sprzętowe, to może kup najtańszą kartę do przygotowania rozwiązania, a docelowo odpal to na maszynach w AWS np.
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/accelerated-computing-instances.html#gpu-instance-families
https://aws.amazon.com/marketplace/pp/NVIDIA-NVIDIA-CUDA-Toolkit-75-on-Amazon-Linux/B01LZMLK1K

Tylko zrób to szybko, bo płacisz za czas. :) Nie wiem jaka jest perspektywa czasowa tego zadania, ale jeśli ma to być jednorazowa akcja, to
chyba nie ma sensu wrzucać kasy w sprzęt, który wykorzystasz raz (no chyba, że jesteś graczem ;)).

Dziękuję za odpowiedź. Niestety nie jest to jednorazowe/krótkotrwałe zadanie do policzenia. Raczej jest budżet, jak budżet się
rozejdzie, to sprzęt pójdzie na wyprzedaż, a liczenie się skończy :)

A mam jeszcze takie pytanie, czy w CUDA można osiągnąć lepszą wydajność niż w OpenCL, czy obie technologie mają takie
same możliwości pod tym względem? CUDA mnie zniechęca bo jest tylko na NVIDIE, jakby np. nadarzyła się okazja użycia
FPGA, to z tego co Koledzy pisali, w OpenCL jest to chociaż teoretycznie możliwe. Więc pytanie, czy w zamian za tę wadę,
CUDA chociaż daje możliwość lepszej implementacji tych samych algorytmów?

Pozdrawiam

1

czy w CUDA można osiągnąć lepszą wydajność niż w OpenCL, czy obie technologie mają takie same możliwości pod tym względem?

CUDA vs OpenCL w Google + dwie minuty poświęconego czasu wskazują na to, że czasem to OpenCL jest wydajniejsze, a czasem CUDA - ogólnie jednak nie są to większe różnice.

0
Patryk27 napisał(a):

czy w CUDA można osiągnąć lepszą wydajność niż w OpenCL, czy obie technologie mają takie same możliwości pod tym względem?

CUDA vs OpenCL w Google + dwie minuty poświęconego czasu wskazują na to, że czasem to OpenCL jest wydajniejsze, a
czasem CUDA - ogólnie jednak nie są to większe różnice.

Rzeczywiście, to można łatwo wygooglać. Resztę najwyraźniej będę musiał sprawdzić własnoręcznie.
Kupię jakąś lepszą kartę na próbę i wrzucę wyniki do tego wątku.

Pozdrawiam

1

Moja praca mgr dotyczyla porownania tych dwóch technologii. Implementowalem mnozenie macierzy i jedrn z algorytmow sortowania. Informacji o CUDA C jest sporo w ksiazce z Helionu .Wyszla w 2012 r

0
szydlak napisał(a):

Moja praca mgr dotyczyla porownania tych dwóch technologii. Implementowalem mnozenie macierzy i jedrn z algorytmow sortowania. Informacji o CUDA C jest sporo w ksiazce z Helionu .Wyszla w 2012 r

Jakie było podsumowanie tej pracy (odnośnie wydajności) ?

0

Pisałem 7 lat temu i już nie pamiętam dokładnie. Ale wydaje mi się, że było zbliżone wydajnościowo. Ale w CUDA C przyjemniej mi się pisało i więcej materiałów miałem. Moja karta wtedy miała 96 rdzeni CUDA. Obecne Geforcy mają od 1000 wzwyż.

0

A inne pytanie, jakie były różnice w wydajności pomiędzy CPU a GPU?

Jeszcze taka moja mała dygresja. Mnożenie macierzy można zrealizować na wiele sposobów. Każdy sposób da
inne czasy (a nawet wyniki!) na innym sprzęcie i na innych wymiarach macierzy. Trudno wyciągać wnioski na
podstawie pomiarów. Podobno ATLAS (https://en.wikipedia.org/wiki/Automatically_Tuned_Linear_Algebra_Software)
sam optymalizuje parametry. Ale czy umie zoptymalizować ilość transferów, dobór algorytmu, podział na kawałki
mieszczące się w pamięci cache i to wszystko w zależności od dostępnego sprzętu?

Pozdrawiam

0
Lenos napisał(a):

A inne pytanie, jakie były różnice w wydajności pomiędzy CPU a GPU?

Kiedyś widziałem porównania (na stronie nvidii) między rozwiązaniami CUDA a CPU.
Różnica była x5 do x100 na korzyść CUDA.
Przy czym x100 to taski głównie zorientowane na mikro-dane (jak napisałem wyżej).
Ile w tym prawdy nie wiem.
Dzisiaj do zrównoleglania na CPU masz wiele rozwiązań i sprzęt ma coraz więcej rdzeni.
Kiedyś (2013) szałem były karty 57 rdzeniowe.
Dzisiaj u Intela dostaniesz 56 rdzeni na jednym CPU a u AMD 32.

1
Lenos napisał(a):

A inne pytanie, jakie były różnice w wydajności pomiędzy CPU a GPU?

Dobrałęm sie do mojej pracy i wyniki były takie:

mnożenie macierzy (A[3250][3250] * B[3250][3250] )

czas w sekundach:

CPU: 2455,28 s.
CUDA C: 23,382633 s
Open CL : 9,316559 s

Sortowanie: Rank Sort (enumeration sort) rozmiar tablicy: 100 000
czas w sekundach:
CPU: 53,135700
CUDA C: 4,169465
OPEN CL: 0,443835

1

W mnozeniu macierzy zaleznie od wielkosci -> od 10x do 100-~120x jesli chodzi o high lvl api typu Pytorch, tensorflow, cupy etc.

0
vpiotr napisał(a):
Lenos napisał(a):

A inne pytanie, jakie były różnice w wydajności pomiędzy CPU a GPU?

Kiedyś widziałem porównania (na stronie nvidii) między rozwiązaniami CUDA a CPU.
Różnica była x5 do x100 na korzyść CUDA.

Dzięki wszystkim za odpowiedzi, takie ogólne informacje dają dobry pogląd dla kogoś
takiego jak ja, czyli dla początkującego z GPU.

Przy czym x100 to taski głównie zorientowane na mikro-dane (jak napisałem wyżej).
Ile w tym prawdy nie wiem.

Co to są mikro-dane? Czy np. problem skoczka szachowego, który wymaga z 100-500
bajtów danych, będzie miał przyspieszenie 100 razy? Albo gdy danych jest więcej, ale
odczyt jest sekwencyjny, czy też można uzyskać przyspieszenie 100 razy? I kolejne
pytanie, gdy w danym okresie czasu porównujemy najlepsze na rykun GPU i CPU, to jest
100 razy względem pełnego wykorzystania procesora, czy względem jednego
wątku na CPU?

Dzisiaj do zrównoleglania na CPU masz wiele rozwiązań i sprzęt ma coraz więcej rdzeni.
Kiedyś (2013) szałem były karty 57 rdzeniowe.

XEON PHI To za droga zabawka dla mnie, ale faktycznie wygoda powala, można to
normalnie programować np. w OpenMP.

Dzisiaj u Intela dostaniesz 56 rdzeni na jednym CPU a u AMD 32.

A dziś widzę że karta ma w ogóle rożne rodzaje procesorów, albo czegoś nie rozumiem:
https://en.wikipedia.org/wiki/GeForce_16_series#Products

W kolumnie Core Config mamy np.: 89632:14 (Shader Processors : Texture mapping units : Render output units : Streaming multi-processors)
I do tego tylko 75 wat :)

Z tego co wiem to przyspieszasz nie od ilosci danych ale od tego ile obliczen "rownolegle" robisz. Male dane raczej srednio dzialaja na GPU bo koszt
przeniesienia danych na GPU jest?(tutaj znak zapytania bo nie jestem pewien ale kiedys to testowalem i w moim wypadku byl) wiekszy

Weźmy dla uszczegółowienia kilka przypadków. W każdym przypadku pamięć algorytmu zawsze mieści się w pamięci karty grafiki, np. jeden
transfer do karty i potem długie 60 sekund obliczeń, albo nawet cała doba obliczeń.

  1. Każdy wątek działa na swoich adresach pamięci, dane są małe, każdy wątek ma np. swoje 500 bajtów do odczytu i swoje 10 bajtów do zapisu.
  2. Każdy wątek działa na swoich adresach pamięci, dane są duże każdy wątek ma np. swoje 5MB do odczytu i swoje 10 bajtów do zapisu - odczyt
    sekwencyjny.
  3. Każdy wątek działa na swoich adresach pamięci, dane są duże każdy wątek ma np. swoje 5MB do odczytu i swoje 10 bajtów do zapisu - odczyt
    losowy po kilkaset bajtów.
  4. Każdy wątek działa na wspólnej dużej (np. 4GB) pamięci do odczytu i na swoich danych do zapisu - odczyty sekwencyjne.
  5. Każdy wątek działa na wspólnej dużej (np. 4GB) pamięci do odczytu i na swoich danych do zapisu - odczyty z losowych miejsc.

Który z powyższych przypadków lepiej a który gorzej się zrównolegli na GPU? Powiedzmy że teoretycznie problem zrównolegla się liniowo,
czyli N procesorów daje N-krotne przyspieszenie, problemem mogą być tylko wąskie gardła w dostępie do pamięci (ale już te dostępy
wewnątrz GPU, bo że transfery są wolne to wiadomo i to inna sprawa).

Pozdrawiam

Pozdrawiam

1

Jeśli nigdy nic nie robiłeś na GPU to warto odkopać jakąś dokumentacje, albo wykłady z jakiejś uczelni, bo niestety jest dużo pułapek po drodze. Poza tym ile danych przetwarzasz, zależy też jak je przetwarzasz

0

Warto sprawdzić i OpenCL i CUDA.
Problem z OpenCL jest taki, że nvidia wspiera tylko wersję 1.x (a nie 2.x) ... i tak już od ładnych paru lat. Jak masz kartę nvidia to sobie nie poszalejesz. Na kartach Nvidia CUDA powinno oferować więcej pod względem funkcjonalności, a także wydajności.

0

Trzeba się po prostu zabrać za kodowanie i samemu się przekonać ;-)
Pobaw się z np.
www quantstart com/articles/Matrix-Matrix-Multiplication-on-the-GPU-with-Nvidia-CUDA
github com/CNugteren/myGEMM?files=1 (jest tam przykład nagłówka OpenCL -> CUDA)
Plus OpenCL to fakt że prawie każdy procesor Intel'a ma wbudowane GPU, nie są to może powalające ilości, ale zawsze kilka kerneli jest i można się pobawić.

Przy okazji nVidia ma całkiem sporo dokumentacji:
github com/NVIDIA/open-gpu-doc

0

Przeglądnij Professional Cuda C programming oraz Cuda Handbook, obie są warte uwagi(zwróć uwagę na SIMD, cache coherence, divergence branch na warpach, shared vs global memory, pamięc textur).
Do debugowania wykorzystaj: Parallel Nsight
Jeżeli chodzi o optymalizację, poczytaj materiały od Vasilya Volkova, fajnie wprowadza w temat.
Jak masz jakieś pytania, łap mnie na pm.

1 użytkowników online, w tym zalogowanych: 0, gości: 1