Révision: Les Rapids de Nvidia apportent l'analyse Python au GPU

La création de modèles d'apprentissage automatique est un processus répétitif. Souvent par cœur et par routine, il s'agit d'un jeu où «le plus rapide à travers le cycle gagne», car plus vous pouvez itérer rapidement, plus il est facile d'explorer de nouvelles théories et d'obtenir de bonnes réponses. C'est l'une des raisons pour lesquelles l'utilisation pratique de l'IA en entreprise est aujourd'hui dominée par les plus grandes entreprises, qui peuvent consacrer d'énormes ressources au problème.

Rapids est un parapluie pour plusieurs projets open source, incubés par Nvidia, qui place l'ensemble du pipeline de traitement sur le GPU, éliminant les transferts de données liés aux E / S, tout en augmentant considérablement la vitesse de chacune des étapes individuelles. Il fournit également un format commun pour les données, allégeant ainsi le fardeau de l'échange de données entre des systèmes disparates. Au niveau de l'utilisateur, Rapids imite l'API Python afin de faciliter la transition pour cette base d'utilisateurs.

Le livre de recettes Tidyverse

Architecture de l'écosystème des rapides

Le projet Rapids vise à répliquer, pour l'essentiel, les API d'apprentissage automatique et d'analyse de données de Python, mais pour des GPU plutôt que des CPU. Cela signifie que les développeurs Python ont déjà tout ce dont ils ont besoin pour s'exécuter sur le GPU, sans avoir à apprendre les détails de bas niveau de la programmation CUDA et des opérations parallèles. Les pythonistes peuvent développer du code sur une machine non compatible GPU, puis, avec quelques ajustements, l'exécuter sur tous les GPU disponibles.

La boîte à outils Nvidia CUDA fournit des primitives de niveau inférieur pour les bibliothèques mathématiques, les algorithmes parallèles et l'analyse de graphes. Au cœur de l'architecture se trouve la trame de données GPU, basée sur Apache Arrow, qui fournit une structure de données en colonne en mémoire indépendante du langage de programmation. L'utilisateur interagit avec la trame de données GPU via cuDF et une API de type Pandas. Dask, une bibliothèque Python pour le calcul parallèle, imite les API Python en amont et fonctionne avec les bibliothèques CUDA pour le calcul parallèle. Considérez Dask comme Spark pour Python.

RAPIDES

Les trois projets principaux, cuDF, cuML et cuGraph, sont développés indépendamment, mais conçus pour fonctionner ensemble de manière transparente. Des ponts vers l'écosystème Python plus large sont également en cours de développement dans le cadre du projet.

Installation rapide

L'installation via Anaconda sur une machine Linux dans AWS était la plupart du temps simple, sauf quelques ratés dus à un changement de dépendances dans la version 0.11. L'installation des bibliothèques C / C ++ pour utiliser libcudf n'a pas été si facile, et je recommanderais de s'en tenir aux API Python et au processus d'installation de Conda. Rapids comprend un bloc-notes Jupyter, également disponible sur Colab gratuit de Google, qui facilite la mise en route. J'ai utilisé la version 0.10 du notebook Jupyter pour exécuter le code sur Google Colab, qui comprend un GPU Nvidia Tesla T4.

La trame de données GPU de Rapids

Le dataframe est au cœur de tout workflow de science des données. C'est là que se déroule l'ingénierie des fonctionnalités et où la majorité du temps est consacrée, alors que les scientifiques des données se débattent avec des données sales. cuDF est le projet Rapids pour une base de données de type Pandas basée sur GPU. À la base de cuDF est libcudf, une bibliothèque C ++ implémentant des primitives de bas niveau pour importer des données Apache Arrow, effectuer des mathématiques élémentaires sur des tableaux et exécuter des opérations de tri, de jointure, de regroupement, de réduction et d'autres opérations sur des matrices de mémoire intégrées au GPU. La structure de données de base de libcudf est le GPU DataFrame (GDF), qui à son tour est modelé sur le magasin de données en colonnes d'Apache Arrow.

RAPIDES

La bibliothèque Rapids Python présente à l'utilisateur une interface de niveau supérieur ressemblant à des dataframes, comme celles de Pandas. Dans de nombreux cas, le code Pandas s'exécute inchangé sur cuDF. Lorsque ce n'est pas le cas, seules des modifications mineures sont généralement nécessaires.

Fonctions définies par l'utilisateur dans cuDF

Une fois que vous avez terminé la manipulation des données de base, il est parfois nécessaire de traiter les lignes et les colonnes avec des fonctions définies par l'utilisateur (UDF). cuDF fournit une API de style PyData pour écrire du code afin de traiter davantage de structures de données granulométriques telles que des tableaux, des séries et des fenêtres mobiles. Actuellement, seuls les types numériques et booléens sont pris en charge. Les UDF sont compilés à l'aide du compilateur Numba JIT, qui utilise un sous-ensemble de LLVM pour compiler des fonctions numériques en code machine CUDA. Cela se traduit par des temps d'exécution nettement plus rapides sur le GPU.

Chaînes en cuDF

Bien que les GPU soient fantastiques pour traiter rapidement les vecteurs flottants, ils n'ont généralement pas été utilisés pour traiter des données de chaîne, et la réalité est que la plupart des données nous parviennent sous forme de chaînes. cuStrings est une bibliothèque de manipulation de chaînes GPU pour fractionner, appliquer des expressions régulières, concaténer, remplacer des jetons, etc. dans des tableaux de chaînes. Comme d'autres fonctions de cuDF, il est implémenté comme une bibliothèque C / C ++ (libnvStrings) et enveloppé par une couche Python conçue pour imiter les Pandas. Bien que le type de données chaîne ne soit pas optimisé pour une exécution sur des GPU, l'exécution parallèle du code devrait permettre une accélération de la manipulation de chaînes basée sur le processeur.

Obtenir des données dans ou hors de cuDF

Les E / S Dataframe sont gérées par une bibliothèque dédiée, cuIO. Tous les formats les plus courants sont pris en charge, notamment Arrow, ORC, Parquet, HDF5 et CSV. Si vous avez la chance de fonctionner sur du matériel DGX-2, vous pouvez utiliser l'intégration GPU Direct Storage pour déplacer les données directement du stockage haute vitesse vers le GPU sans impliquer le CPU. Les utilisateurs mortels apprécieront toujours l'accélération du GPU lors de la décompression de grands ensembles de données et l'intégration étroite avec l'écosystème Python.

GPU Direct Storage est actuellement en version alpha, et une fois publié, il sera disponible sur la plupart des GPU Tesla. Vous pouvez créer une trame de données GPU à partir de tableaux NumPy, de Pandas DataFrames et de tables PyArrow avec une seule ligne de code. D'autres projets peuvent échanger des données via le __cuda_array_interface__pour les bibliothèques appartenant à l'écosystème Numba. DLPack pour les bibliothèques de réseaux neuronaux est également une interface prise en charge.

Le plus gros inconvénient de l'utilisation de cuDF est probablement le manque d'interopérabilité en dehors de Python. Je pense que se concentrer sur une base solide d'API C / C ++, comme Arrow l'a fait, permettrait un écosystème plus large et profiterait au projet dans son ensemble.

CuML des rapides

Les objectifs déclarés de cuML sont d'être «Scikit-learn de Python alimenté par des GPU». En théorie, cela signifie que vous ne devriez avoir qu'à modifier votre instruction d'importation et peut-être régler quelques paramètres pour tenir compte des différences de fonctionnement sur un processeur, où parfois une approche par force brute est préférable. L'avantage d'avoir un Scikit-learn basé sur GPU est difficile à sous-estimer. Les accélérations sont substantielles et les analystes de données peuvent être plusieurs fois plus productifs. L'API C ++ n'est pas tout à fait prête pour une large consommation en dehors de ses liaisons Python, mais cela devrait s'améliorer.

cuML comprend également des API pour aider à l'ajustement d'hyperparamètres via Dask, une bibliothèque pour faire évoluer Python sur plusieurs nœuds. De nombreux algorithmes d'apprentissage automatique peuvent être efficacement mis en parallèle, et cuML développe activement des algorithmes multi-GPU et multi-nœuds, multi-GPU.

RAPIDES

Graphique des Rapids

cuGraph est le troisième membre de l'écosystème Rapids, et comme les autres, cuGraph est entièrement intégré à cuDF et cuML. Il offre une bonne sélection d'algorithmes graphiques, de primitives et d'utilitaires, tous avec des performances accélérées par le GPU. La sélection d'API dans cuGraph est un peu plus étendue que dans d'autres parties de Rapids, avec NetworkX, Pregel, GraphBLAS et GQL (Graph Query Language) tous disponibles.

RAPIDES

cuGraph ressemble plus à une boîte à outils dans l'esprit qu'à cuML. La technologie graphique est un espace en évolution rapide tant dans le milieu universitaire que dans l'industrie. Ainsi, de par sa conception, cuGraph permet aux développeurs d'accéder à la couche C ++ et aux primitives graphiques, encourageant les tiers à développer des produits en utilisant cuGraph. Plusieurs universités ont contribué, et des projets de Texas A&M (GraphBLAS), Georgia Tech (Hornet) et UC Davis (Gunrock) ont été «produits» et inclus sous l'égide de cuGraph. Chaque projet fournit un ensemble différent de capacités, toutes accélérées par GPU et toutes soutenues par la même trame de données cuDF.

NetworkX est l'API Python ciblée par l'équipe Rapids pour son interface native. Il existe un certain nombre d'algorithmes disponibles via cette interface. Alors que seul le classement de page est multi-GPU, l'équipe travaille activement sur des versions multi-GPU des autres, le cas échéant.

RAPIDES

L'un des sous-projets cuGraph que j'ai trouvé intéressant est cugraphBLAS, un effort pour standardiser les blocs de construction pour les algorithmes de graphes dans le langage de l'algèbre linéaire. Basé sur GraphBLAS (graphblas.org), une structure de données personnalisée conçue pour le traitement de graphiques dynamiques clairsemés.

Un autre sous-projet cuGraph, Hornet fournit un format indépendant du système pour contenir des données graphiques, analogue à la façon dont Apache arrow fournit un moyen indépendant du système pour traiter les dataframes. Hornet prend en charge la plupart des formats de graphiques populaires, y compris SNAP, mtx, metis et bords.

Fidèle à l'esprit de proximité avec la communauté Python, le package NetworkX natif de Python peut être utilisé pour l'étude de réseaux complexes. Cela inclut les structures de données pour les graphiques et les multi-graphiques, réimplémentées à l'aide de primitives CUDA, vous permettant de réutiliser de nombreux algorithmes de graphique standard et d'effectuer des mesures de structure et d'analyse de réseau. La majorité des algorithmes sont mono-GPU, comme NetworkX. Néanmoins, les exécuter sur le GPU seul offre une accélération significative, tandis que le travail continue à se déplacer vers des implémentations multi-GPU.

Sur la feuille de route des rapides 

Compte tenu de l'énorme rapidité offerte par l'analyse basée sur le GPU, quelques nouveaux projets seront ajoutés dans les versions futures.

DLPack et array_interface pour un apprentissage en profondeur

Les réseaux de neurones multicouches ont été l'une des premières charges de travail déplacées vers les GPU, et un corps de code important existe pour ce cas d'utilisation de l'apprentissage automatique. Auparavant, DLPack était la norme de facto pour l'échange de données entre les bibliothèques d'apprentissage en profondeur. De nos jours, le array_interface est généralement pris en charge. Rapids prend en charge les deux.

CuSignal

Comme la plupart des autres projets chez Rapids, cuSignal est une version accélérée par GPU d'une bibliothèque Python existante, dans ce cas la bibliothèque SciPy Signal. La bibliothèque originale de SciPy Signal est basée sur NumPy, qui est remplacée par son équivalent accéléré par GPU, CuPy dans cuSignal. C'est un bon exemple de la philosophie de conception des Rapids à l'œuvre. À l'exception de quelques noyaux CUDA personnalisés, le portage vers le GPU implique principalement le remplacement de l'instruction d'importation et la modification de quelques paramètres de fonction. 

Amener le traitement du signal dans le giron des Rapids est une décision intelligente. Le traitement du signal est partout et a de nombreuses applications commerciales immédiatement utiles dans l'industrie et la défense.

cuSpatial

Les opérations spatiales et spatio-temporelles sont d'excellents candidats pour l'accélération GPU et résolvent de nombreux problèmes du monde réel auxquels nous sommes confrontés dans la vie quotidienne, tels que l'analyse des modèles de trafic, la santé / qualité des sols et les risques d'inondations. Une grande partie des données collectées par les appareils mobiles, y compris les drones, a une composante géospatiale, et l'analyse spatiale est au cœur de la Smart City. 

Architecturé comme les autres composants, cuSpatial est une bibliothèque C ++ construite sur les primitives CUDA et la bibliothèque de traitement vectoriel Thrust, utilisant cuDF pour l'échange de données. Les utilisateurs de la bibliothèque C ++ peuvent lire les données de points, de polylignes et de polygones à l'aide d'un lecteur C ++. Les utilisateurs de Python ont intérêt à utiliser des packages Python existants tels que Shapely ou Fiona pour remplir un tableau NumPy, puis à utiliser l'API cuSpatial Python ou à convertir en dataframes cuDF. 

cuxfilter pour la visualisation des données

La visualisation des données est fondamentale, à la fois dans le flux de travail analytique et pour la présentation ou le reporting des résultats. Pourtant, malgré toute la magie que les GPU peuvent travailler sur les données elles-mêmes, transmettre ces données à un navigateur n'est pas une tâche triviale. cuxfilter, inspiré de la bibliothèque JavaScript Crossfilter, vise à combler cette lacune en fournissant une pile permettant aux bibliothèques de visualisation tierces d'afficher des données dans des dataframes cuDF.

Il y a eu quelques itérations de cuxfilter pendant que l'équipe trie les meilleurs modèles d'architecture et de connecteur. La dernière itération exploite les blocs-notes Jupyter, le serveur Bokeh et les panneaux PyViz, tandis que les expériences d'intégration incluent des projets d'Uber, Falcon et PyDeck. Ce composant n'est pas encore prêt pour les heures de grande écoute, mais devrait sortir dans Rapids 0.13. Il y a beaucoup de pièces mobiles, et je n'ai pas pu l'expérimenter de première main, mais s'il tient ses promesses, ce sera un excellent ajout à la boîte à outils Rapids.

Élargissement et déploiement avec Dask

Dask est un planificateur de tâches distribué pour Python, jouant un rôle similaire pour Python qu'Apache Spark joue pour Scala. Dask-cuDF est une bibliothèque qui fournit des dataframes partitionnées, basées sur GPU. Dask-cuDF fonctionne bien lorsque vous prévoyez d'utiliser cuML ou lorsque vous chargez un ensemble de données plus volumineux que la mémoire du GPU ou réparti sur plusieurs fichiers.

Comme un Spark RDD (Resilient Distributed Dataset), la trame de données distribuée Dask-cuDF se comporte principalement comme une trame locale, vous pouvez donc expérimenter avec votre machine locale et passer à un modèle distribué lorsque vous avez besoin de passer à l'échelle. Dask-cuML offre des capacités multi-nœuds cuML, ce qui en fait une bonne option lorsque vous n'avez pas le budget pour un poste de travail DGX.