Qu'est-ce que CUDA? Programmation parallèle pour les GPU

CUDA est une plate-forme de calcul parallèle et un modèle de programmation développé par Nvidia pour le calcul général sur ses propres GPU (unités de traitement graphique). CUDA permet aux développeurs d'accélérer les applications gourmandes en calcul en exploitant la puissance des GPU pour la partie parallélisable du calcul.

Bien qu'il y ait eu d'autres API proposées pour les GPU, telles que OpenCL, et qu'il existe des GPU concurrents d'autres sociétés, telles que AMD, la combinaison de GPU CUDA et Nvidia domine plusieurs domaines d'application, y compris l'apprentissage en profondeur, et constitue la base de certains des les ordinateurs les plus rapides du monde.

Les cartes graphiques sont sans doute aussi anciennes que le PC, c'est-à-dire si vous considérez l'adaptateur d'affichage monochrome IBM 1981 comme une carte graphique. En 1988, vous pourriez obtenir une carte VGA Wonder 16 bits 2D auprès d'ATI (société finalement rachetée par AMD). En 1996, vous pourriez acheter un accélérateur graphique 3D de 3dfx Interactive afin de pouvoir exécuter le jeu de tir à la première personne Quake à pleine vitesse.

Toujours en 1996, Nvidia a commencé à essayer de rivaliser sur le marché des accélérateurs 3D avec des produits faibles, mais a appris au fur et à mesure et en 1999 a présenté la GeForce 256 à succès, la première carte graphique à s'appeler GPU. À l'époque, la principale raison d'avoir un GPU était le jeu. Ce n'est que plus tard que les gens ont utilisé les GPU pour les mathématiques, les sciences et l'ingénierie.

L'origine de CUDA

En 2003, une équipe de chercheurs dirigée par Ian Buck a dévoilé Brook, le premier modèle de programmation largement adopté pour étendre C avec des constructions parallèles aux données. Buck a ensuite rejoint Nvidia et a dirigé le lancement de CUDA en 2006, la première solution commerciale pour l'informatique générale sur GPU.

OpenCL contre CUDA

OpenCL, concurrent de CUDA, a été lancé par Apple et le groupe Khronos en 2009, dans le but de fournir une norme pour le calcul hétérogène qui ne se limite pas aux processeurs Intel / AMD avec GPU Nvidia. Bien qu'OpenCL semble attrayant en raison de sa généralité, il n'a pas fonctionné aussi bien que CUDA sur les GPU Nvidia, et de nombreux frameworks d'apprentissage en profondeur ne le prennent pas en charge ou ne le prennent en charge qu'après coup une fois que leur support CUDA a été publié.

Augmentation des performances CUDA

CUDA a amélioré et élargi sa portée au fil des ans, plus ou moins en parallèle avec des GPU Nvidia améliorés. À partir de la version 9.2 de CUDA, en utilisant plusieurs GPU de serveur P100, vous pouvez réaliser des améliorations de performances jusqu'à 50 fois par rapport aux CPU. Le V100 (non illustré sur cette figure) est encore 3 fois plus rapide pour certaines charges. La génération précédente de GPU serveur, le K80, offrait des améliorations de performances de 5x à 12x par rapport aux processeurs.

Nvidia

L'augmentation de la vitesse des GPU est venue à point nommé pour le calcul haute performance. L'augmentation des performances à un seul thread des processeurs au fil du temps, que la loi de Moore suggérait de doubler tous les 18 mois, a ralenti à 10% par an, les fabricants de puces rencontrant des limites physiques, notamment des limites de taille sur la résolution du masque de puce et le rendement de la puce pendant le processus de fabrication et les limites de chaleur sur les fréquences d'horloge au moment de l'exécution.

Nvidia

Domaines d'application CUDA

Nvidia

Les GPU CUDA et Nvidia ont été adoptés dans de nombreux domaines nécessitant des performances de calcul en virgule flottante élevées, comme le montre l'image ci-dessus. Une liste plus complète comprend:

  1. Finance informatique
  2. Modélisation du climat, de la météo et des océans
  3. Science et analyse des données
  4. Apprentissage profond et apprentissage automatique
  5. Défense et renseignement
  6. Fabrication / AEC (architecture, ingénierie et construction): CAO et IAO (y compris la dynamique des fluides computationnelle, la mécanique structurelle computationnelle, la conception et la visualisation et l'automatisation de la conception électronique)
  7. Médias et divertissement (y compris l'animation, la modélisation et le rendu; la correction des couleurs et la gestion du grain; la composition; la finition et les effets; l'édition; l'encodage et la distribution numérique; les graphiques à l'antenne; les outils sur le plateau, la revue et la stéréo; et les graphiques météorologiques)
  8. L'imagerie médicale
  9. Pétrole et gaz
  10. Recherche: Enseignement supérieur et supercalcul (y compris la chimie et la biologie computationnelles, l'analyse numérique, la physique et la visualisation scientifique)
  11. Sûreté et sécurité
  12. Outils et gestion

CUDA en apprentissage profond

Le Deep Learning a un besoin démesuré de vitesse de calcul. Par exemple, pour former les modèles pour Google Translate en 2016, les équipes Google Brain et Google Translate ont effectué des centaines d'exécutions TensorFlow d'une semaine à l'aide de GPU; ils avaient acheté 2000 GPU de qualité serveur à Nvidia à cette fin. Sans GPU, ces sessions de formation auraient pris des mois plutôt qu'une semaine pour converger. Pour le déploiement en production de ces modèles de traduction TensorFlow, Google a utilisé une nouvelle puce de traitement personnalisée, le TPU (Tensor Processing Unit).

En plus de TensorFlow, de nombreux autres frameworks DL s'appuient sur CUDA pour leur prise en charge de GPU, notamment Caffe2, CNTK, Databricks, H2O.ai, Keras, MXNet, PyTorch, Theano et Torch. Dans la plupart des cas, ils utilisent la bibliothèque cuDNN pour les calculs du réseau neuronal profond. Cette bibliothèque est si importante pour la formation des frameworks d'apprentissage profond que tous les frameworks utilisant une version donnée de cuDNN ont essentiellement les mêmes chiffres de performances pour des cas d'utilisation équivalents. Lorsque CUDA et cuDNN s'améliorent d'une version à l'autre, tous les frameworks d'apprentissage en profondeur qui se mettent à jour vers la nouvelle version voient des gains de performances. Là où les performances ont tendance à différer d'un framework à l'autre, c'est dans leur capacité à s'adapter à plusieurs GPU et à plusieurs nœuds.

Programmation CUDA

Nvidia

Boîte à outils CUDA

La boîte à outils CUDA comprend des bibliothèques, des outils de débogage et d'optimisation, un compilateur, de la documentation et une bibliothèque d'exécution pour déployer vos applications. Il comporte des composants qui prennent en charge l'apprentissage en profondeur, l'algèbre linéaire, le traitement du signal et les algorithmes parallèles. En général, les bibliothèques CUDA prennent en charge toutes les familles de GPU Nvidia, mais fonctionnent mieux sur la dernière génération, telle que la V100, qui peut être 3 fois plus rapide que la P100 pour les charges de travail de formation en apprentissage profond. Utiliser une ou plusieurs bibliothèques est le moyen le plus simple de tirer parti des GPU, à condition que les algorithmes dont vous avez besoin aient été implémentés dans la bibliothèque appropriée.

Nvidia

Bibliothèques d'apprentissage en profondeur CUDA

Dans le domaine de l'apprentissage profond, il existe trois principales bibliothèques accélérées par GPU: cuDNN, que j'ai mentionné plus tôt comme le composant GPU pour la plupart des frameworks d'apprentissage profond open source; TensorRT, qui est l'optimiseur et l'exécution d'inférence d'apprentissage en profondeur hautes performances de Nvidia; et DeepStream, une bibliothèque d'inférence vidéo. TensorRT vous aide à optimiser les modèles de réseaux neuronaux, à calibrer pour une précision inférieure avec une grande précision et à déployer les modèles formés dans les nuages, les centres de données, les systèmes embarqués ou les plates-formes de produits automobiles.

Nvidia

Bibliothèques d'algèbre linéaire et de mathématiques CUDA

L'algèbre linéaire sous-tend les calculs tensoriels et donc l'apprentissage en profondeur. BLAS (Basic Linear Algebra Subprograms), un ensemble d'algorithmes matriciels mis en œuvre dans Fortran en 1989, est utilisé depuis par les scientifiques et les ingénieurs. cuBLAS est une version accélérée par GPU de BLAS et le moyen le plus performant de faire de l'arithmétique matricielle avec des GPU. cuBLAS suppose que les matrices sont denses; cuSPARSE gère les matrices clairsemées.

Nvidia

Bibliothèques de traitement du signal CUDA

La transformée de Fourier rapide (FFT) est l'un des algorithmes de base utilisés pour le traitement du signal; il transforme un signal (tel qu'une forme d'onde audio) en un spectre de fréquences. cuFFT est une FFT accélérée par GPU.

Les codecs, utilisant des normes telles que H.264, encodent / compressent et décodent / décompressent la vidéo pour transmission et affichage. Le SDK Nvidia Video Codec accélère ce processus avec les GPU.

Nvidia

Bibliothèques d'algorithmes parallèles CUDA

Les trois bibliothèques d'algorithmes parallèles ont toutes des objectifs différents. NCCL (Nvidia Collective Communications Library) permet de faire évoluer les applications sur plusieurs GPU et nœuds; nvGRAPH est destiné à l'analyse de graphes parallèles; and Thrust est une bibliothèque de modèles C ++ pour CUDA basée sur la bibliothèque de modèles standard C ++. Thrust fournit une riche collection de primitives parallèles de données telles que l'analyse, le tri et la réduction.

Nvidia

CUDA vs performances du processeur

Dans certains cas, vous pouvez utiliser des fonctions CUDA à la place des fonctions CPU équivalentes. Par exemple, les routines de multiplication de matrice GEMM de BLAS peuvent être remplacées par des versions GPU simplement en se connectant à la bibliothèque NVBLAS:

Nvidia

Principes de base de la programmation CUDA

Si vous ne trouvez pas les routines de la bibliothèque CUDA pour accélérer vos programmes, vous devrez vous essayer à la programmation CUDA de bas niveau. C'est beaucoup plus facile maintenant que lorsque je l'ai essayé pour la première fois à la fin des années 2000. Entre autres raisons, il existe une syntaxe plus simple et de meilleurs outils de développement disponibles. Mon seul problème est que sur MacOS, le dernier compilateur CUDA et le dernier compilateur C ++ (de Xcode) sont rarement synchronisés. Il faut télécharger les anciens outils de ligne de commande d'Apple et les utiliser xcode-selectpour obtenir le code CUDA à compiler et à lier.

Par exemple, considérez cette simple routine C / C ++ pour ajouter deux tableaux:

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

{  

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

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

}

Vous pouvez le transformer en un noyau qui s'exécutera sur le GPU en ajoutant le __global__mot - clé à la déclaration, et appeler le noyau en utilisant la syntaxe du triple crochet:

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

Vous devez également modifier vos appels malloc/ newet free/ deletevers cudaMallocManagedet cudaFreepour que vous allouiez de l'espace sur le GPU. Enfin, vous devez attendre la fin d'un calcul GPU avant d'utiliser les résultats sur le processeur, ce que vous pouvez accomplir avec cudaDeviceSynchronize.

Le support triple ci-dessus utilise un bloc de filetage et un filetage. Les GPU Nvidia actuels peuvent gérer de nombreux blocs et threads. Par exemple, un GPU Tesla P100 basé sur l'architecture GPU Pascal possède 56 multiprocesseurs de streaming (SM), chacun capable de prendre en charge jusqu'à 2048 threads actifs.

Le code du noyau devra connaître son index de bloc et de thread pour trouver son offset dans les tableaux passés. Le noyau parallélisé utilise souvent une boucle de quadrillage , telle que la suivante:

__global__

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

{

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

   int stride = blockDim.x * gridDim.x;

   pour (int i = index; i <n; i + = foulée)

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

}

Si vous regardez les exemples dans la boîte à outils CUDA, vous verrez qu'il y a plus à considérer que les bases que j'ai couvertes ci-dessus. Par exemple, certains appels de fonction CUDA doivent être encapsulés dans des checkCudaErrors()appels. En outre, dans de nombreux cas, le code le plus rapide utilisera des bibliothèques telles que les cuBLASallocations de mémoire d'hôte et de périphérique et la copie des matrices dans les deux sens.

En résumé, vous pouvez accélérer vos applications avec des GPU à plusieurs niveaux. Vous pouvez écrire du code CUDA; vous pouvez appeler les bibliothèques CUDA; et vous pouvez utiliser des applications qui prennent déjà en charge CUDA.