Une grande nouveauté de CUDA 10 facilitera l’expression de programmes de calcul compliqués, où certaines opérations ne peuvent être lancées que quand d’autres sont terminées : par exemple, on ne peut copier les résultats d’un calcul sur le processeur central que quand il a fini de s’exécuter sur la carte graphique. CUDA disposait déjà de la notion de flux, mais elle n’autorisait pas une grande flexibilité : le processeur central doit toujours gérer l’ordonnancement des tâches, par exemple. Lancer un noyau de calcul prend toujours un certain temps, non négligeable quand le noyau est assez petit.
L’idée des graphes de calcul est donc d’indiquer à CUDA les tâches à exécuter et leurs dépendances, de telle sorte que la carte graphique ou le pilote puisse décider, sans attendre l’application, des tâches à exécuter par la suite. Dans le cas de noyaux très rapides à l’exécution dans un processus plus long, les coûts de lancement sont en grande partie éliminés. Également, CUDA peut réordonner les tâches afin d’améliorer les temps d’exécution, notamment en réduisant les mouvements de données : la carte graphique sait quand des données seront réutilisées, par exemple.
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | cudaGraphCreate(&graph); cudaGraphAddNode(graph, kernel_a, {}, ...); cudaGraphAddNode(graph, kernel_b, { kernel_a }, ...); cudaGraphAddNode(graph, kernel_c, { kernel_a }, ...); cudaGraphAddNode(graph, kernel_d, { kernel_b, kernel_c }, ...); cudaGraphInstantiate(&instance, graph); for(int i = 0; i < 100; i++) cudaGraphLaunch(instance, stream); |
Source : CUDA 10 Features Revealed: Turing, CUDA Graphs and More.
Et vous ?
Qu'en pensez-vous ?