Optimiser l'utilisation des GPU pour les réseaux de neurones
Un nouveau cadre améliore les performances des GPU pour les tâches d'apprentissage profond.
― 10 min lire
Table des matières
- Comprendre Pourquoi Certaines Applications Sous-Utilisent les GPU
- Moteurs de Simulation pour l'Apprentissage par Renforcement Profond
- Réseaux Neuronaux Dynamiques
- Défis pour l'Exécution Concurrente des Noyaux
- Défi 1 : Graphes de Calcul Dépendants des Entrées
- Défi 2 : Dépendances Irregulières Entre les Noyaux
- Notre Solution : Un Nouveau Cadre
- Approche Purement Logicielle (-SW)
- Approche Coopérative Matériel-Logiciel (-HW)
- Évaluation du Cadre
- 1. Simulations d'Apprentissage par Renforcement Profond
- 2. Réseaux Neuronaux Dynamiques
- 3. Réseaux Neuronaux Statique
- Conclusion
- Source originale
Les unités de traitement graphique (GPU) modernes jouent un rôle énorme dans l'accélération de nombreuses tâches importantes aujourd'hui. Cependant, certains nouveaux types d'applications, comme les moteurs de simulation pour l'Apprentissage par renforcement profond et les réseaux neuronaux dynamiques, n'utilisent pas les GPU à leur plein potentiel. C'est parce que ces applications ont généralement de petites tâches (ou Noyaux) qui ne peuvent pas garder le GPU assez occupé. Quand ces petites tâches s'exécutent les unes après les autres, au lieu de le faire en même temps, ça peut gaspiller beaucoup de puissance de calcul. Une bonne solution à ce problème est de faire tourner des tâches indépendantes en même temps. Mais c'est compliqué car les dépendances entre les tâches changent avec les différentes entrées, et ces dépendances sont difficiles.
Dans notre travail, on présente un cadre qui peut facilement vérifier ces dépendances entre les tâches en temps réel et les programmer sans trop de délais. L'idée principale est de regarder un petit nombre de tâches à la fois et de vérifier leurs dépendances, un peu comme les processeurs modernes font avec des instructions. Ça permet d'exécuter simultanément des tâches dans des applications où l'ordre d'exécution des tâches n'est pas fixe et nécessite une Planification soignée. On a créé deux versions de notre cadre : une qui fonctionne uniquement grâce au logiciel et une autre qui combine logiciel et support matériel pour réduire encore plus les délais causés par la communication entre le CPU et le GPU.
On a testé notre cadre sur diverses applications, en particulier dans l'apprentissage par renforcement profond et différents types de réseaux neuronaux. Les résultats étaient encourageants, montrant qu'on pouvait accélérer le traitement de manière significative tout en utilisant mieux le GPU.
Comprendre Pourquoi Certaines Applications Sous-Utilisent les GPU
Les GPU sont régulièrement utilisés pour accélérer des tâches comme le traitement de réseaux neuronaux profonds, les calculs scientifiques, le rendu graphique et la cryptographie. Les capacités parallèles étendues des GPU leur permettent de gérer rapidement de grandes quantités de données. Cependant, certaines applications, surtout dans des domaines comme l'apprentissage par renforcement profond et les réseaux neuronaux dynamiques, n'exploitent pas pleinement les capacités des GPU.
Une des raisons est que ces applications dépendent de nombreuses petites tâches qui ne peuvent pas pleinement activer la puissance de traitement du GPU. On a exploré deux classes d'applications pour identifier les problèmes causant cette sous-utilisation.
Moteurs de Simulation pour l'Apprentissage par Renforcement Profond
Dans l'apprentissage par renforcement profond, un agent, comme un robot, apprend à réaliser des tâches par essais et erreurs en interagissant avec son environnement. Entraîner un agent implique l'utilisation d'un réseau neuronal profond (DNN) pour développer des stratégies qui maximisent les récompenses en fonction des données collectées à partir d'environnements simulés.
Bien que les DNN puissent bénéficier de la puissance des GPU, une grande partie du temps d'exécution de l'apprentissage par renforcement profond est consacrée à la collecte de données, ce qui peut parfois prendre jusqu'à 90 % du temps total. Pendant cette phase, des simulations physiques génèrent des données d'entraînement. Cependant, on a découvert que ces simulations n'utilisent pas efficacement le GPU, atteignant seulement environ 30 % de sa capacité totale en moyenne. Cette inefficacité provient du fait que les petits noyaux dans les simulations ne peuvent pas pleinement solliciter les ressources du GPU, rendant impraticable la création de plus grands noyaux puisque chaque tâche simule différents scénarios.
Réseaux Neuronaux Dynamiques
Les récents développements dans les réseaux neuronaux dynamiques montrent du potentiel pour réduire le temps nécessaire à ces réseaux pour faire des prédictions sur des appareils à puissance limitée. Ces réseaux peuvent ajuster leur structure en fonction de l'entrée qu'ils reçoivent. Par exemple, certains modèles peuvent changer leur architecture en temps réel en fonction de l'image d'entrée.
On a découvert que, bien que ces réseaux dynamiques utilisent moins d'opérations en virgule flottante et aient des temps de prédiction plus courts, ils n'utilisent toujours pas efficacement les ressources du GPU, atteignant un taux d'occupation moyen de seulement 39 %. Tout comme les moteurs de simulation, cette inefficacité est attribuée à de petits noyaux qui n'engagent pas pleinement les cœurs du GPU.
Les noyaux GPU des deux types d'applications sont généralement exécutés en séquence, ce qui signifie que la capacité du GPU est limitée par la taille et le nombre de threads dans chaque noyau. Cependant, beaucoup de ces noyaux sont indépendants, ce qui leur permet d'être exécutés simultanément. En exécutant ces noyaux indépendants en même temps, on peut améliorer l'utilisation du GPU et augmenter les performances.
Défis pour l'Exécution Concurrente des Noyaux
Bien que faire tourner des noyaux indépendants en même temps soit une bonne solution pour améliorer les performances, ce n'est pas facile à mettre en œuvre pour plusieurs raisons.
Défi 1 : Graphes de Calcul Dépendants des Entrées
Dans de nombreuses applications, les dépendances entre les noyaux ne sont déterminées qu'en temps réel en fonction des données d'entrée. Cela signifie que chaque entrée ou ensemble d'entrées peut mener à une disposition différente des noyaux qui doivent être exécutés. Quand c'est le cas, vérifier les dépendances entre les noyaux devient nécessaire mais aussi long, surtout puisque beaucoup de ces tâches ont des durées d'exécution courtes.
Les outils existants peuvent aider à définir les dépendances et à créer un graphe acyclique dirigé de noyaux, ce qui permettrait une exécution concurrente. Cependant, ces outils nécessitent souvent un temps significatif pour préparer le graphe de dépendance pour chaque exécution de l'application, ce qui peut ralentir le traitement global.
Défi 2 : Dépendances Irregulières Entre les Noyaux
Un autre problème est que les graphes de calcul peuvent être imprévisibles. À cause de cette imprévisibilité, il peut être difficile de les partitionner en groupes indépendants pour une exécution parallèle. Une planification fine est essentielle pour découvrir le parallélisme inter-noyaux. Ce besoin de synchronisation fréquente peut introduire une surcharge considérable à cause de la communication nécessaire avec le CPU.
Notre Solution : Un Nouveau Cadre
Pour surmonter ces défis, on propose un nouveau cadre pour automatiser la planification concurrente des noyaux qui nécessite un minimum de surcharge pour le suivi des dépendances. Ce cadre a deux implémentations : une qui fonctionne purement en logiciel et une autre qui exploite les capacités matérielles pour réduire encore plus les surcharges.
Caractéristiques Clés de Notre Cadre
- Le cadre vérifie les dépendances entre les noyaux dans un groupe limité en temps réel, utilisant une méthode similaire à la planification d'instructions désordonnées.
- Quand un noyau entre dans la fenêtre de planification, il identifie automatiquement quels noyaux il dépend. Une fois qu'un noyau a fini de s'exécuter, les noyaux dépendants peuvent être lancés en même temps s'ils n'ont plus de dépendances restantes.
- Des annotations fournies par l'application aident le cadre à identifier les plages d'adresses mémoire que chaque noyau lit ou écrit, qui sont ensuite utilisées pour vérifier les dépendances en temps réel.
Approche Purement Logicielle (-SW)
L'implémentation -SW fonctionne comme un système d'exécution qui utilise des flux CUDA existants pour programmer des noyaux indépendants en même temps. Bien qu'elle soit efficace, elle a encore une certaine surcharge de synchronisation lors de la communication avec le CPU.
Approche Coopérative Matériel-Logiciel (-HW)
L'implémentation -HW intègre à la fois des éléments logiciels et matériels. Elle utilise le matériel pour gérer la fenêtre de planification, ce qui aide à réduire considérablement la communication avec le CPU. Ce modèle matériel garde une trace des dépendances de manière efficace pour simplifier la planification et l'exécution des noyaux.
Évaluation du Cadre
On a testé notre cadre avec diverses applications pour mesurer les améliorations en utilisation du GPU et en performances globales.
1. Simulations d'Apprentissage par Renforcement Profond
On a examiné plusieurs environnements de simulation physique pour l'apprentissage par renforcement profond, comme Ant, Grasp, Humanoid, Cheetah et Walker2d. Ces simulations nécessitent des données de milliers de courses, et on a observé comment différents modèles se comportaient sous notre cadre.
Les résultats ont montré que notre cadre pouvait améliorer les performances en augmentant l'utilisation du GPU, conduisant à des gains de vitesse allant jusqu'à 4,5 fois par rapport aux méthodes de base.
2. Réseaux Neuronaux Dynamiques
Ensuite, on a évalué notre cadre sur des réseaux neuronaux dynamiques en utilisant trois charges de travail spécifiques : InstaNAS, Dynamic Routing et Conditional Convolution. Ces modèles sont conçus pour s'ajuster en fonction de l'entrée qu'ils reçoivent, ce qui les rend idéaux pour les tests.
Encore une fois, notre cadre a fourni des résultats impressionnants, avec des gains de vitesse allant de 2 à 3 fois par rapport aux modèles de base sur diverses itérations.
3. Réseaux Neuronaux Statique
Pour les réseaux neuronaux statiques, on a testé plusieurs architectures populaires qui tendent à avoir des structures fixes. Notre cadre a quand même donné des améliorations de performance, atteignant des gains de vitesse d'environ 1,5 à 2 fois par rapport aux méthodes traditionnelles.
Conclusion
En conclusion, notre cadre offre une solution pratique au défi d'exécuter des noyaux indépendants simultanément dans des applications avec des graphes de calcul irréguliers. En permettant une planification efficace et des vérifications de dépendance en temps réel, on peut considérablement améliorer l'utilisation du GPU et les performances globales dans les applications d'apprentissage par renforcement profond et de réseaux neuronaux dynamiques.
Ce travail souligne la nécessité de meilleures approches pour gérer les tâches qui dépendent de conditions d'entrée dynamiques, ouvrant la voie à un calcul plus efficace à l'avenir. Les résultats obtenus grâce à nos implémentations purement logicielles et coopératives matériel-logiciel démontrent le potentiel d'accélérations substantielles dans des applications réelles. Cette avancée constitue un pas vers l'optimisation des ressources du GPU pour une plus large gamme d'applications, abordant la sous-utilisation actuellement rencontrée dans de nombreuses charges de travail émergentes.
Titre: ACS: Concurrent Kernel Execution on Irregular, Input-Dependent Computational Graphs
Résumé: GPUs are widely used to accelerate many important classes of workloads today. However, we observe that several important emerging classes of workloads, including simulation engines for deep reinforcement learning and dynamic neural networks, are unable to fully utilize the massive parallelism that GPUs offer. These applications tend to have kernels that are small in size, i.e., have few thread blocks that do not saturate compute resources. Executing independent kernels concurrently is a promising approach to improve parallelism and utilization. However, this inter-kernel concurrency is difficult to leverage in such workloads with existing approaches: First, the inter-kernel dependencies and computational graph are input-dependent and vary each time the application is executed. Second, the computational graphs tend to be irregular, requiring fine-grain scheduling and synchronization; thus incurring significant synchronization overheads if kernel execution is parallelized. In this work, we propose ACS, a framework that enables lightweight detection of inter-kernel dependencies and low overhead kernel scheduling at runtime. The key idea behind ACS is to perform inter-kernel dependency checks for a small window of kernels at runtime, similar to out-of order instruction scheduling. This enables concurrent execution of kernels in applications whose computational graphs are input dependent and require fine-grained scheduling. We propose ACS-SW, a software-only open-source implementation of ACS and ACS-HW, a hardware-software cooperative implementation. ACS-HW further reduces synchronization overheads by reducing communication between the CPU and GPU. We evaluate ACS for deep RL simulation and dynamic DNNs on both real hardware and a GPU simulator. We demonstrate speedups of up to 2.19x (1.56x on average) by improving GPU utilization with concurrent kernel execution.
Auteurs: Sankeerth Durvasula, Adrian Zhao, Raymond Kiguru, Yushi Guan, Zhonghan Chen, Nandita Vijaykumar
Dernière mise à jour: 2024-01-22 00:00:00
Langue: English
Source URL: https://arxiv.org/abs/2401.12377
Source PDF: https://arxiv.org/pdf/2401.12377
Licence: https://creativecommons.org/licenses/by/4.0/
Changements: Ce résumé a été créé avec l'aide de l'IA et peut contenir des inexactitudes. Pour obtenir des informations précises, veuillez vous référer aux documents sources originaux dont les liens figurent ici.
Merci à arxiv pour l'utilisation de son interopérabilité en libre accès.