Co to jest CUDA? Programowanie równoległe dla GPU

CUDA to równoległa platforma obliczeniowa i model programowania opracowany przez firmę Nvidia do ogólnych obliczeń na jej własnych GPU (procesorach graficznych). CUDA umożliwia programistom przyspieszenie aplikacji wymagających dużej mocy obliczeniowej poprzez wykorzystanie mocy procesorów graficznych do równoległej części obliczeń.

Chociaż pojawiły się inne proponowane interfejsy API dla procesorów graficznych, takie jak OpenCL, i istnieją konkurencyjne procesory graficzne innych firm, takich jak AMD, połączenie procesorów graficznych CUDA i Nvidia dominuje w kilku obszarach zastosowań, w tym w uczeniu głębokim, i stanowi podstawę niektórych najszybsze komputery na świecie.

Karty graficzne są prawdopodobnie tak stare jak komputery PC - to znaczy, jeśli weźmie się pod uwagę kartę graficzną IBM Monochrome Display Adapter z 1981 roku. Do 1988 roku można było dostać 16-bitową kartę 2D VGA Wonder od ATI (firma ostatecznie przejęta przez AMD). Do 1996 roku można było kupić akcelerator grafiki 3D od 3dfx Interactive, aby móc uruchomić strzelankę pierwszoosobową Quake z pełną prędkością.

Również w 1996 roku Nvidia zaczęła próbować konkurować na rynku akceleratorów 3D ze słabymi produktami, ale nauczyła się na bieżąco, aw 1999 roku wprowadziła udany GeForce 256, pierwszą kartę graficzną, którą nazwano GPU. W tamtym czasie głównym powodem posiadania GPU były gry. Dopiero później ludzie używali procesorów graficznych do matematyki, nauk ścisłych i inżynierii.

Pochodzenie CUDA

W 2003 roku zespół badaczy pod kierownictwem Iana Bucka zaprezentował Brook, pierwszy szeroko przyjęty model programowania, który rozszerza język C o konstrukcje równoległe do danych. Buck dołączył później do Nvidii i w 2006 r. Wprowadził na rynek CUDA, pierwsze komercyjne rozwiązanie do obliczeń ogólnego przeznaczenia na procesorach graficznych.

OpenCL kontra CUDA

Konkurent CUDA, OpenCL, został uruchomiony przez Apple i Khronos Group w 2009 roku, jako próba zapewnienia standardu heterogenicznych obliczeń, który nie był ograniczony do procesorów Intel / AMD z procesorami graficznymi Nvidia. Chociaż OpenCL brzmi atrakcyjnie ze względu na swoją ogólność, nie działał tak dobrze, jak CUDA na procesorach graficznych Nvidia, a wiele platform do głębokiego uczenia albo go nie obsługuje, albo obsługuje go dopiero po namyśle po udostępnieniu obsługi CUDA.

Wzrost wydajności CUDA

CUDA udoskonaliła i poszerzyła swój zakres przez lata, mniej więcej w ślad za ulepszonymi procesorami graficznymi Nvidia. Począwszy od wersji CUDA 9.2, używając wielu serwerowych procesorów graficznych P100, można osiągnąć nawet 50-krotną poprawę wydajności w porównaniu z procesorami. V100 (nie pokazany na tym rysunku) jest jeszcze 3x szybszy w przypadku niektórych obciążeń. Poprzednia generacja procesorów graficznych dla serwerów, K80, oferowała od 5 do 12 razy większą wydajność niż procesory.

Nvidia

Zwiększenie szybkości dzięki procesorom graficznym nadeszło w ostatniej chwili w przypadku wysokowydajnych obliczeń. Jednowątkowy wzrost wydajności procesorów w czasie, który według prawa Moore'a podwajał się co 18 miesięcy, spowolnił do 10 procent rocznie, ponieważ producenci chipów napotkali ograniczenia fizyczne, w tym ograniczenia rozmiaru dotyczące rozdzielczości maski i wydajności chipa podczas procesu produkcyjnego i ograniczenia ciepła dla częstotliwości zegara w czasie pracy.

Nvidia

Domeny aplikacji CUDA

Nvidia

Procesory graficzne CUDA i Nvidia zostały zastosowane w wielu obszarach, które wymagają wysokiej wydajności obliczeń zmiennoprzecinkowych, jak podsumowano obrazowo na powyższym obrazku. Bardziej obszerna lista obejmuje:

  1. Finanse obliczeniowe
  2. Modelowanie klimatu, pogody i oceanów
  3. Nauka i analiza danych
  4. Uczenie głębokie i uczenie maszynowe
  5. Obrona i inteligencja
  6. Produkcja / AEC (Architektura, Inżynieria i Konstrukcja): CAD i CAE (w tym obliczeniowa dynamika płynów, obliczeniowa mechanika konstrukcji, projektowanie i wizualizacja oraz automatyzacja projektowania elektronicznego)
  7. Media i rozrywka (w tym animacja, modelowanie i renderowanie; korekcja kolorów i zarządzanie ziarnem; kompozycja; wykończenie i efekty; edycja; kodowanie i dystrybucja cyfrowa; grafika nadawana na żywo; narzędzia na planie, przegląd i stereo; oraz grafika pogodowa)
  8. Obrazowanie medyczne
  9. Olej i gaz
  10. Badania: szkolnictwo wyższe i superkomputery (w tym chemia obliczeniowa i biologia, analityka numeryczna, fizyka i wizualizacja naukowa)
  11. Bezpieczeństwo i ochrona
  12. Narzędzia i zarządzanie

CUDA w uczeniu głębokim

Głębokie uczenie wymaga dużej szybkości obliczeniowej. Na przykład, aby wytrenować modele dla Tłumacza Google w 2016 r., Zespoły Google Brain i Tłumacz Google wykonały setki tygodniowych uruchomień TensorFlow przy użyciu procesorów graficznych; w tym celu kupili 2000 procesorów graficznych klasy serwerowej od firmy Nvidia. Bez GPU te szkolenia zajęłyby miesiące, a nie tydzień. Do wdrożenia produkcyjnego tych modeli translacji TensorFlow firma Google wykorzystała nowy niestandardowy układ przetwarzający, TPU (tensor Processing Unit).

Oprócz TensorFlow wiele innych frameworków DL opiera się na CUDA w zakresie obsługi GPU, w tym Caffe2, CNTK, Databricks, H2O.ai, Keras, MXNet, PyTorch, Theano i Torch. W większości przypadków używają biblioteki cuDNN do obliczeń głębokich sieci neuronowych. Ta biblioteka jest tak ważna dla szkolenia platform uczenia głębokiego, że wszystkie platformy korzystające z danej wersji cuDNN mają zasadniczo te same wskaźniki wydajności dla równoważnych przypadków użycia. Gdy CUDA i cuDNN ulepszają się z wersji na wersję, wszystkie platformy głębokiego uczenia, które aktualizują się do nowej wersji, widzą wzrost wydajności. Tam, gdzie wydajność zwykle różni się w zależności od platformy, jest to, jak dobrze można ją skalować do wielu procesorów graficznych i wielu węzłów.

Programowanie CUDA

Nvidia

Zestaw narzędzi CUDA

Zestaw narzędzi CUDA zawiera biblioteki, narzędzia do debugowania i optymalizacji, kompilator, dokumentację i bibliotekę wykonawczą do wdrażania aplikacji. Posiada komponenty obsługujące głębokie uczenie się, algebrę liniową, przetwarzanie sygnałów i algorytmy równoległe. Ogólnie rzecz biorąc, biblioteki CUDA obsługują wszystkie rodziny procesorów graficznych Nvidia, ale działają najlepiej na najnowszej generacji, takiej jak V100, która może być 3 razy szybsza niż P100 w przypadku obciążeń związanych z uczeniem głębokim. Korzystanie z jednej lub więcej bibliotek to najłatwiejszy sposób wykorzystania GPU, o ile potrzebne algorytmy zostały zaimplementowane w odpowiedniej bibliotece.

Nvidia

Biblioteki głębokiego uczenia CUDA

W sferze uczenia głębokiego istnieją trzy główne biblioteki akcelerowane przez GPU: cuDNN, o którym wspomniałem wcześniej jako komponent GPU dla większości frameworków głębokiego uczenia o otwartym kodzie źródłowym; TensorRT, czyli wysokowydajny optymalizator wnioskowania głębokiego uczenia firmy Nvidia i środowisko wykonawcze; i DeepStream, bibliotekę wnioskowania wideo. TensorRT pomaga zoptymalizować modele sieci neuronowych, przeprowadzić kalibrację w celu uzyskania niższej precyzji z dużą dokładnością i wdrożyć wyszkolone modele w chmurach, centrach danych, systemach wbudowanych lub platformach produktów motoryzacyjnych.

Nvidia

Biblioteki algebry liniowej i matematyki CUDA

Algebra liniowa stanowi podstawę obliczeń tensorowych, a tym samym głębokiego uczenia się. BLAS (Basic Linear Algebra Subprograms), zbiór algorytmów macierzowych zaimplementowanych w Fortranie w 1989 roku, jest od tamtego czasu używany przez naukowców i inżynierów. cuBLAS to wersja BLAS z akceleracją GPU i najbardziej wydajnym sposobem wykonywania arytmetyki macierzowej z GPU. cuBLAS zakłada, że ​​matryce są gęste; cuSPARSE obsługuje rzadkie matryce.

Nvidia

Biblioteki przetwarzania sygnałów CUDA

Szybka transformata Fouriera (FFT) jest jednym z podstawowych algorytmów wykorzystywanych do przetwarzania sygnałów; zamienia sygnał (taki jak przebieg audio) w spektrum częstotliwości. cuFFT to przyspieszany przez GPU FFT.

Kodeki, wykorzystujące standardy takie jak H.264, kodują / kompresują i dekodują / dekompresują wideo do transmisji i wyświetlania. Nvidia Video Codec SDK przyspiesza ten proces w przypadku układów GPU.

Nvidia

Biblioteki algorytmów równoległych CUDA

Wszystkie trzy biblioteki do równoległych algorytmów mają różne cele. NCCL (Nvidia Collective Communications Library) służy do skalowania aplikacji w wielu procesorach graficznych i węzłach; nvGRAPH służy do równoległej analizy wykresów; and Thrust to biblioteka szablonów C ++ dla CUDA oparta na standardowej bibliotece szablonów C ++. Thrust zapewnia bogatą kolekcję równoległych danych pierwotnych, takich jak skanowanie, sortowanie i redukcja.

Nvidia

CUDA a wydajność procesora

W niektórych przypadkach można użyć wbudowanych funkcji CUDA zamiast odpowiadających im funkcji procesora. Na przykład procedury mnożenia macierzy GEMM z BLAS można zastąpić wersjami GPU, po prostu łącząc się z biblioteką NVBLAS:

Nvidia

Podstawy programowania w CUDA

Jeśli nie możesz znaleźć procedur bibliotecznych CUDA, które przyspieszą twoje programy, będziesz musiał spróbować swoich sił w programowaniu w CUDA niskiego poziomu. Teraz jest o wiele łatwiej niż wtedy, gdy po raz pierwszy spróbowałem tego pod koniec 2000 roku. Między innymi jest łatwiejsza składnia i dostępne są lepsze narzędzia programistyczne. Moim jedynym zastrzeżeniem jest to, że na MacOS najnowszy kompilator CUDA i najnowszy kompilator C ++ (z Xcode) rzadko są zsynchronizowane. Należy pobrać starsze narzędzia wiersza poleceń z Apple i przełączyć się na nie za pomocą xcode-selectkodu CUDA do kompilacji i linkowania.

Na przykład rozważmy tę prostą procedurę C / C ++, aby dodać dwie tablice:

void add (int n, float * x, float * y)

{  

       dla (int i = 0; i <n; i ++)      

             y [i] = x [i] + y [i];

}

Możesz przekształcić go w jądro, które będzie działało na GPU, dodając __global__słowo kluczowe do deklaracji i wywołać jądro, używając składni potrójnego nawiasu:

dodaj << >> (N, x, y);

Trzeba też zmienić malloc/ newi free/ deletepołączenia do cudaMallocManagedi cudaFreetak, że jesteś przydzielenie miejsca na GPU. Na koniec musisz poczekać na zakończenie obliczeń GPU, zanim użyjesz wyników na CPU, co możesz zrobić cudaDeviceSynchronize.

W powyższym potrójnym wsporniku zastosowano jeden blok gwintowany i jeden gwint. Obecne procesory graficzne Nvidia mogą obsługiwać wiele bloków i wątków. Na przykład procesor graficzny Tesla P100 oparty na architekturze GPU Pascal ma 56 wieloprocesorów strumieniowych (SM), z których każdy może obsługiwać do 2048 aktywnych wątków.

Kod jądra będzie musiał znać swój indeks bloku i wątku, aby znaleźć przesunięcie w przekazanych tablicach. Zrównoleglone jądro często używa pętli grid-stride , takiej jak:

__światowy__

void add (int n, float * x, float * y)

{

   int index = blockIdx.x * blockDim.x + threadIdx.x;

   int stride = blockDim.x * gridDim.x;

   for (int i = index; i <n; i + = stride)

     y [i] = x [i] + y [i];

}

Jeśli spojrzysz na próbki w CUDA Toolkit, zobaczysz, że jest więcej do rozważenia niż podstawy, które omówiłem powyżej. Na przykład niektóre wywołania funkcji CUDA muszą być opakowane w checkCudaErrors()wywołania. Ponadto w wielu przypadkach najszybszy kod będzie korzystał z bibliotek, takich jak cuBLASalokacje pamięci hosta i urządzenia oraz kopiowanie macierzy w tę iz powrotem.

Podsumowując, możesz przyspieszyć swoje aplikacje za pomocą procesorów graficznych na wielu poziomach. Możesz pisać kod CUDA; możesz dzwonić do bibliotek CUDA; i możesz używać aplikacji, które już obsługują CUDA.