API de pilote CUDA et runtime CUDA

Lorsque vous écrivez des applications CUDA, vous pouvez travailler soit au niveau du pilote, soit au niveau de l’exécution, comme illustré sur cette image (les bibliothèques sont CUFFT et CUBLAS pour les mathématiques avancées):

Modèle de couche CUDA

Je suppose que le compromis entre les deux est une performance accrue pour l’API low-evel, mais au prix d’une complexité accrue du code. Quelles sont les différences concrètes et y a-t-il des choses importantes que vous ne pouvez pas faire avec l’API de haut niveau?

J’utilise CUDA.net pour l’interopérabilité avec C # et il est conçu comme une copie de l’API du pilote. Cela encourage à écrire beaucoup de code plutôt complexe en C # alors que l’équivalent C ++ serait plus simple en utilisant l’API d’exécution. Y at-il quelque chose à gagner en le faisant de cette façon? Le seul avantage que je peux constater est qu’il est plus facile d’intégrer la gestion intelligente des erreurs au rest du code C #.

Le runtime CUDA permet de comstackr et de lier vos kernelx CUDA en exécutables. Cela signifie que vous n’avez pas besoin de dissortingbuer des fichiers cubin avec votre application, ni de les charger via l’API du pilote. Comme vous l’avez noté, il est généralement plus facile à utiliser.

En revanche, l’API du pilote est plus difficile à programmer, mais elle permet de mieux contrôler l’utilisation de CUDA. Le programmeur doit s’occuper directement de l’initialisation, du chargement du module, etc.

Apparemment, des informations plus détaillées sur le périphérique peuvent être interrogées via l’API du pilote plutôt que via l’API d’exécution. Par exemple, la mémoire disponible disponible sur le périphérique ne peut être interrogée que via l’API du pilote.

Du Guide du programmeur CUDA:

Il est composé de deux API:

  • Une API de bas niveau appelée API du pilote CUDA,
  • API de niveau supérieur appelée API d’exécution CUDA implémentée par dessus l’API du pilote CUDA.

Ces API s’excluent mutuellement: une application doit utiliser l’un ou l’autre.

Le moteur d’exécution CUDA facilite la gestion du code de périphérique en fournissant l’initialisation implicite, la gestion du contexte et la gestion des modules. Le code de l’hôte C généré par nvcc est basé sur le moteur d’exécution CUDA (voir la section 4.2.5). Par conséquent, les applications liées à ce code doivent utiliser l’API d’exécution CUDA.

En revanche, l’API du pilote CUDA nécessite plus de code, est plus difficile à programmer et à déboguer, mais offre un meilleur niveau de contrôle et est indépendante de la langue puisqu’elle ne traite que des objects cubin (voir Section 4.2.5). En particulier, il est plus difficile de configurer et de lancer des kernelx à l’aide de l’API du pilote CUDA, car la configuration d’exécution et les parameters du kernel doivent être spécifiés avec des appels de fonction explicites au lieu de la syntaxe de configuration d’exécution décrite à la Section 4.2.3. De même, l’émulation de périphérique (voir la section 4.5.2.9) ne fonctionne pas avec l’API du pilote CUDA.

Il n’y a pas de différence de performance notable entre les API. La manière dont vos kernelx utilisent la mémoire et leur disposition sur le GPU (en chaînes et en blocs) aura un effet beaucoup plus prononcé.

J’ai constaté que pour le déploiement de bibliothèques dans des applications multithreads, le contrôle du contexte CUDA fourni par l’API du pilote était essentiel. La plupart de mes clients souhaitent intégrer l’accélération GPU dans les applications existantes. Aujourd’hui, presque toutes les applications sont multi-threadées. Comme je ne pouvais pas garantir que tout le code GPU serait initialisé, exécuté et désalloué à partir du même thread, je devais utiliser l’API du pilote.

Mes tentatives initiales avec diverses solutions de contournement dans l’API d’exécution ont toutes conduit à des échecs, parfois spectaculaires. J’ai constaté que je pouvais redémarrer plusieurs fois instantanément une machine en effectuant le mauvais ensemble d’appels CUDA à partir de différents threads.

Depuis que nous avons tout migré via l’API du pilote, tout va bien.

J

quelques points importants à noter:

Tout d’abord, les différences entre les API ne s’appliquent qu’au code côté hôte. Les kernelx sont exactement les mêmes. Du côté de l’hôte, la complexité de l’API de pilote est assez sortingviale, les différences fondamentales sont les suivantes:

dans l’API de pilote, vous avez access à des fonctionnalités qui ne sont pas disponibles dans l’API d’exécution, comme les contextes.

l’émulateur ne fonctionne qu’avec du code écrit pour l’API d’exécution.

oh et actuellement cudpp qui est une bibliothèque très pratique ne fonctionne qu’avec l’API d’exécution.

L’alignement des arguments et l’API du pilote posent de réels problèmes. Consultez la documentation bêta de CUDA 2.2 (ou ultérieure) pour plus d’informations.