Recenzja: Rapids firmy Nvidia przenosi analizę Pythona do GPU

Budowanie modeli uczenia maszynowego to powtarzalny proces. Często rutynowa i rutynowa gra polegająca na „najszybszych wygranych w cyklu”, ponieważ im szybciej możesz iterować, tym łatwiej jest odkrywać nowe teorie i uzyskiwać dobre odpowiedzi. Jest to jeden z powodów, dla których praktyczne wykorzystanie sztucznej inteligencji w przedsiębiorstwach jest dziś zdominowane przez największe przedsiębiorstwa, które mogą przeznaczyć na ten problem olbrzymie zasoby.

Rapids jest parasolem dla kilku projektów open source, inkubowanych przez Nvidię, które umieszczają cały potok przetwarzania na GPU, eliminując transfery danych związane z I / O, a jednocześnie znacznie zwiększając szybkość każdego z poszczególnych kroków. Zapewnia również wspólny format danych, zmniejszając obciążenie związane z wymianą danych między różnymi systemami. Na poziomie użytkownika Rapids naśladuje interfejs API języka Python, aby ułatwić przejście dla tej bazy użytkowników.

Książka kucharska Tidyverse

Rapids architektura ekosystemu

Projekt Rapids ma na celu w większości replikację interfejsów API do uczenia maszynowego i analizy danych w języku Python, ale raczej dla GPU niż CPU. Oznacza to, że programiści Pythona mają już wszystko, czego potrzebują do uruchomienia na GPU, bez konieczności uczenia się niskopoziomowych szczegółów programowania CUDA i operacji równoległych. Pythonistas może tworzyć kod na maszynie bez GPU, a następnie, po wprowadzeniu kilku poprawek, uruchamiać go na wszystkich dostępnych GPU.

Zestaw narzędzi Nvidia CUDA zapewnia prymitywy niższego poziomu dla bibliotek matematycznych, algorytmów równoległych i analizy grafów. Sercem architektury jest ramka danych GPU oparta na Apache Arrow, która zapewnia kolumnową strukturę danych w pamięci, która jest niezależna od języka programowania. Użytkownik współdziała z ramką danych GPU za pośrednictwem cuDF i interfejsu API podobnego do Pandy. Dask, biblioteka Pythona do obliczeń równoległych, naśladuje wcześniejsze interfejsy API Pythona i współpracuje z bibliotekami CUDA do obliczeń równoległych. Pomyśl o Dask jako o Spark dla Pythona.

KATARAKTY NA RZECE

Trzy główne projekty, cuDF, cuML i cuGraph, są opracowywane niezależnie, ale zaprojektowane tak, aby bezproblemowo ze sobą współpracować. W ramach projektu opracowywane są również mosty do szerszego ekosystemu Pythona.

Szybka instalacja

Instalacja przez Anacondę na maszynie Linux w AWS była w większości prosta, poza kilkoma problemami spowodowanymi zmianą zależności w wersji 0.11. Instalacja bibliotek C / C ++ w celu korzystania z libcudf nie była taka łatwa i zalecałbym trzymanie się API Pythona i procesu instalacji Conda. Rapids zawiera notebook Jupyter, dostępny również w bezpłatnej usłudze Google Colab, dzięki czemu rozpoczęcie pracy jest proste. Użyłem notebooka Jupyter w wersji 0.10 do uruchomienia kodu w Google Colab, który zawiera procesor graficzny Nvidia Tesla T4.

Ramka danych GPU firmy Rapids

Sercem każdego przepływu pracy w nauce o danych jest ramka danych. To tutaj ma miejsce inżynieria cech i spędza większość czasu, gdy naukowcy zajmujący się danymi majstrują przy brudnych danych. cuDF to projekt Rapids dla opartej na GPU, podobnej do Pandy ramki danych. Podstawą cuDF jest libcudf, biblioteka C ++ implementująca prymitywy niskiego poziomu do importowania danych Apache Arrow, wykonywania elementów matematycznych na tablicach oraz wykonywania operacji sortowania, łączenia, grupowania, redukcji i innych operacji na macierzach pamięci w GPU. Podstawową strukturą danych libcudf jest GPU DataFrame (GDF), która z kolei jest wzorowana na kolumnowym magazynie danych Apache Arrow.

KATARAKTY NA RZECE

Biblioteka Rapids Python przedstawia użytkownikowi interfejs wyższego poziomu, przypominający ramki danych, takie jak w Pandas. W wielu przypadkach kod Pandas działa bez zmian na cuDF. Jeśli tak nie jest, zwykle wymagane są tylko niewielkie zmiany.

Funkcje zdefiniowane przez użytkownika w cuDF

Gdy przejdziesz przez podstawowe operacje na danych, czasami konieczne jest przetwarzanie wierszy i kolumn za pomocą funkcji zdefiniowanych przez użytkownika (UDF). cuDF zapewnia interfejs API w stylu PyData do pisania kodu w celu przetwarzania bardziej uporządkowanych struktur danych, takich jak tablice, serie i ruchome okna. Obecnie obsługiwane są tylko typy liczbowe i logiczne. Funkcje UDF są kompilowane przy użyciu kompilatora Numba JIT, który wykorzystuje podzbiór LLVM do kompilowania funkcji numerycznych do kodu maszynowego CUDA. Powoduje to znacznie krótsze czasy działania na GPU.

Ciągi w cuDF

Chociaż procesory graficzne są fantastyczne do szybkiego przetwarzania wektorów typu float, zazwyczaj nie są używane do przetwarzania danych łańcuchowych, a rzeczywistość jest taka, że ​​większość danych dociera do nas w postaci ciągów. cuStrings to biblioteka obsługująca ciągi GPU do dzielenia, stosowania wyrażeń regularnych, łączenia, zastępowania tokenów itp. w tablicach ciągów. Podobnie jak inne funkcje cuDF, jest zaimplementowana jako biblioteka C / C ++ (libnvStrings) i otoczona warstwą Pythona zaprojektowaną do naśladowania Pandy. Chociaż typ danych łańcuchowych nie jest zoptymalizowany pod kątem wykonywania na procesorach graficznych, równoległe wykonywanie kodu powinno zapewnić przyspieszenie w porównaniu z manipulacją ciągami opartą na procesorze CPU.

Pobieranie danych do lub z cuDF

We / wy Dataframe jest obsługiwane przez dedykowaną bibliotekę cuIO. Obsługiwane są wszystkie najczęściej spotykane formaty, w tym Arrow, ORC, Parquet, HDF5 i CSV. Jeśli masz szczęście pracować na sprzęcie DGX-2, możesz skorzystać z integracji GPU Direct Storage, aby przenieść dane bezpośrednio z pamięci masowej o dużej szybkości do GPU bez angażowania procesora. Śmiertelni użytkownicy nadal docenią przyspieszenie, jakie GPU daje podczas dekompresji dużych zbiorów danych, oraz ścisłą integrację z ekosystemem Pythona.

GPU Direct Storage jest obecnie w wersji alfa i po wydaniu będzie dostępne na większości GPU Tesla. Możesz utworzyć ramkę danych GPU z tablic NumPy, Pandas DataFrames i tabel PyArrow za pomocą tylko jednej linii kodu. Inne projekty mogą wymieniać dane za pośrednictwem __cuda_array_interface__bibliotek for należących do ekosystemu Numba. DLPack dla bibliotek sieci neuronowych jest również obsługiwanym interfejsem.

Prawdopodobnie największą wadą używania cuDF jest brak interoperacyjności poza Pythonem. Myślę, że skupienie się na solidnych podstawach interfejsów API C / C ++, tak jak to zrobiła Arrow, umożliwiłoby szerszy ekosystem i przyniosłoby korzyści całemu projektowi.

CUML firmy Rapids

Deklarowane cele cuML to „nauka języka Python Scikit oparta na procesorach graficznych”. W teorii oznacza to, że wystarczy zmienić instrukcję importu i być może dostroić kilka parametrów, aby uwzględnić różnice w działaniu na procesorze, gdzie czasami podejście brutalnej siły jest lepsze. Korzyści z posiadania Scikit-learning opartego na GPU są trudne do przecenienia. Przyspieszenia są znaczne, a analitycy danych mogą być wielokrotnie bardziej produktywni. Interfejs API C ++ nie jest jeszcze gotowy do szerokiego wykorzystania poza powiązaniami języka Python, ale oczekuje się, że to poprawi.

cuML zawiera również interfejsy API pomagające w dostrajaniu hiperparametrów za pośrednictwem Dask, biblioteki do skalowania Pythona w wielu węzłach. Wiele algorytmów uczenia maszynowego można skutecznie uczynić równoległymi, a cuML aktywnie rozwija zarówno algorytmy wieloprocesorowe, jak i wielowęzłowe, wieloprocesorowe.

KATARAKTY NA RZECE

Rapids 'cuGraph

cuGraph jest trzecim członkiem ekosystemu Rapids i podobnie jak inne, cuGraph jest w pełni zintegrowany z cuDF i cuML. Oferuje duży wybór algorytmów graficznych, prymitywów i narzędzi, wszystkie z wydajnością przyspieszaną przez GPU. Wybór API w cuGraph jest nieco szerszy niż w innych częściach Rapids, z dostępnymi wszystkimi NetworkX, Pregel, GraphBLAS i GQL (Graph Query Language).

KATARAKTY NA RZECE

cuGraph to bardziej zestaw narzędzi w duchu niż cuML. Technologia grafów to szybko zmieniająca się przestrzeń zarówno w środowisku akademickim, jak i przemysłowym. Dlatego też, zgodnie z projektem, cuGraph daje programistom dostęp do warstwy C ++ i prymitywów grafu, zachęcając strony trzecie do opracowywania produktów przy użyciu cuGraph. Kilka uniwersytetów wniosło swój wkład, a projekty z Texas A&M (GraphBLAS), Georgia Tech (Hornet) i UC Davis (Gunrock) zostały „wyprodukowane” i objęte parasolem cuGraph. Każdy projekt zapewnia inny zestaw możliwości, wszystkie przyspieszane przez GPU i wszystkie wspierane przez tę samą ramkę danych cuDF.

NetworkX to interfejs API języka Python, na który zespół Rapids kieruje swój natywny interfejs. Za pośrednictwem tego interfejsu dostępnych jest wiele algorytmów. Chociaż tylko PageRank to multi-GPU, zespół aktywnie pracuje nad wersjami innych GPU, tam gdzie ma to zastosowanie.

KATARAKTY NA RZECE

Jednym z interesujących mnie podprojektów cuGraph jest cugraphBLAS, próba standaryzacji bloków konstrukcyjnych dla algorytmów grafowych w języku algebry liniowej. Oparty na GraphBLAS (graphblas.org), niestandardowej strukturze danych zaprojektowanej do rzadkiego przetwarzania dynamicznych wykresów.

Kolejny podprojekt cuGraph, Hornet, dostarcza niezależny od systemu format do przechowywania danych grafowych, analogiczny do sposobu, w jaki Apache arrow zapewnia niezależny od systemu sposób przetwarzania ramek danych. Hornet obsługuje większość popularnych formatów grafów, w tym SNAP, mtx, metis i edge.

Zgodnie z duchem bliskości społeczności Pythona, natywny pakiet NetworkX języka Python może być używany do badania złożonych sieci. Obejmuje to struktury danych dla wykresów i multigrafów, ponownie zaimplementowane przy użyciu prymitywów CUDA, co pozwala na ponowne wykorzystanie wielu standardowych algorytmów grafowych oraz wykonanie pomiarów struktury i analizy sieci. Większość algorytmów to jeden GPU, jak NetworkX. Niemniej jednak uruchomienie ich na samym GPU zapewnia znaczne przyspieszenie, podczas gdy prace nadal przenoszą się do implementacji z wieloma GPU.

Na mapie drogowej Rapids 

Biorąc pod uwagę ogromne przyspieszenie, jakie zapewnia analiza oparta na GPU, w przyszłych wersjach pojawi się kilka nowych projektów.

DLPack i array_interface do głębokiego uczenia się

Wielowarstwowe sieci neuronowe były jednymi z pierwszych obciążeń przeniesionych na procesory graficzne, a dla tego przypadku zastosowania uczenia maszynowego istnieje pokaźny zbiór kodu. Wcześniej DLPack był de facto standardem wymiany danych między bibliotekami głębokiego uczenia. Obecnie powszechnie obsługiwany jest array_interface. Rapids obsługuje jedno i drugie.

cuSignal

Podobnie jak większość innych projektów w Rapids, cuSignal jest akcelerowaną przez GPU wersją istniejącej biblioteki Pythona, w tym przypadku biblioteki SciPy Signal. Oryginalna biblioteka SciPy Signal jest oparta na NumPy, który został zastąpiony przez przyspieszony przez GPU odpowiednik CuPy w cuSignal. To jest dobry przykład działania filozofii projektowania Rapids. Z wyjątkiem kilku niestandardowych jąder CUDA, przeniesienie do GPU polega głównie na zastąpieniu instrukcji import i dostosowaniu kilku parametrów funkcji. 

Przeniesienie przetwarzania sygnału do zakładki Rapids to sprytne posunięcie. Przetwarzanie sygnału jest wszędzie i ma wiele natychmiastowych przydatnych zastosowań komercyjnych w przemyśle i obronności.

cuSpatial

Operacje przestrzenne i czasoprzestrzenne są doskonałymi kandydatami do akceleracji GPU i rozwiązują wiele rzeczywistych problemów, z którymi borykamy się w życiu codziennym, takich jak analiza wzorców ruchu, stanu / jakości gleby i ryzyka powodzi. Wiele danych gromadzonych przez urządzenia mobilne, w tym drony, zawiera komponent geoprzestrzenny, a analiza przestrzenna jest sercem Smart City. 

Zaprojektowana tak jak inne komponenty cuSpatial to biblioteka C ++ zbudowana na prymitywach CUDA i bibliotece przetwarzania wektorów Thrust, wykorzystująca cuDF do wymiany danych. Użytkownicy biblioteki C ++ mogą odczytywać dane punktów, polilinii i wielokątów przy użyciu czytnika C ++. Użytkownikom Pythona lepiej jest użyć istniejących pakietów Pythona, takich jak Shapely lub Fiona, do wypełnienia tablicy NumPy, a następnie użyć interfejsu API cuSpatial Python lub przekonwertować na ramki danych cuDF. 

cuxfilter do wizualizacji danych

Wizualizacja danych ma fundamentalne znaczenie, zarówno w ramach przepływu pracy analityki, jak i przy prezentowaniu lub raportowaniu wyników. Jednak pomimo całej magii, jaką układy GPU mogą przetwarzać na samych danych, przesłanie tych danych do przeglądarki nie jest prostym zadaniem. cuxfilter, zainspirowany biblioteką Crossfilter JavaScript, ma na celu wypełnienie tej luki poprzez zapewnienie stosu umożliwiającego zewnętrznym bibliotekom wizualizacyjnym wyświetlanie danych w ramkach danych cuDF.

Było kilka iteracji cuxfilter, gdy zespół sortuje najlepszą architekturę i wzorce łączników. Najnowsza iteracja wykorzystuje notebooki Jupyter, serwer Bokeh i panele PyViz, podczas gdy eksperymenty integracyjne obejmują projekty firm Uber, Falcon i PyDeck. Ten komponent nie jest jeszcze gotowy na czas największej oglądalności, ale ma zostać wydany w Rapids 0.13. Jest wiele ruchomych części i nie miałem okazji eksperymentować z nimi z pierwszej ręki, ale jeśli spełni swoje obietnice, będzie to świetny dodatek do zestawu narzędzi Rapids.

Skalowanie w górę i na zewnątrz z Dask

Dask to rozproszony harmonogram zadań dla Pythona, odgrywający podobną rolę w Pythonie, jaką Apache Spark odgrywa w Scali. Dask-cuDF to biblioteka udostępniająca podzielone na partycje, obsługiwane przez GPU ramki danych. Dask-cuDF działa dobrze, gdy planujesz używać cuML lub gdy ładujesz zestaw danych, który jest większy niż pamięć GPU lub jest rozłożony na wiele plików.

Podobnie jak Spark RDD (Resilient Distributed Dataset), rozproszona ramka danych Dask-cuDF w większości zachowuje się tak, jak lokalna, więc możesz eksperymentować z maszyną lokalną i przejść do modelu rozproszonego, gdy musisz zwiększyć skalę. Dask-cuML zapewnia możliwości wielowęzłowe cuML, co czyni go dobrym rozwiązaniem, gdy nie masz budżetu na stację roboczą DGX.