Cuda hello world
Concepts
Le framework CUDA permet d'utiliser le GPU pour faire des calculs généraux, habituellement réalisés par le CPU. CUDA est une extension en C/C++ qui propose une API pour gérer le GPU et elle distingue deux entités:
- l'entité host ou hôte pour le CPU
- l'entité device ou périphérique pour le GPU
De manière générale on essayera de faire le traitement sérialisé sur le CPU et de décharger les calculs parallélisés sur le GPU.
La difficulté réside dans le faite que CPU et GPU utilisent deux espaces mémoire séparés... qu'il va falloir gérer par le biais de pointeurs et fonctions spécifiques !
API CUDA
Les basiques
L'API CUDA permet d'exécuter une fonction sur le GPU grâce à la notation chevrons <<<...>>> :
fonction<<<CORE, THREAD>>>();
- fonction : correspond au nom de la fonction
- CORE : correspond au nombre de cœur CUDA utilisés
- THREAD : correspond au nombre de threads par cœur CUDA
La fonction appelée doit être précédée du spécificateur __global__ pour préciser au compilateur que sont exécution se fait sur le GPU:
__global__ void fonction(){
// choses à faire
}
Les fichiers contenant du code CUDA doivent impérativement porter l'extension .cu et être compilés avec le compilateur CUDA : nvcc
# nvcc hello.cu -o hello
Exemple de programme
Ci-dessous l'exemple classique du Hello World utilisant le CPU:
#include <stdio.h>
int main(void) {
printf("Hello World du CPU\n");
return EXIT_SUCCESS;
}
Si nous voulons utiliser le GPU il faut sortir l'instruction à exécuter (ici le printf) dans une fonction __global__ puis lancer son exécution grâce à la notation chevrons:
#include <stdio.h>
#include <stdlib.h>
#include <cuda_runtime.h>
#include <cuda.h>
__global__ void cuda_hello(){
printf("Hello World du GPU\n");
}
int main(void) {
printf("Hello World du CPU\n");
cuda_hello<<<1,1>>>();
return EXIT_SUCCESS;
}
Synchronisation CPU / GPU
Ce programme affichera le résultat suivant:
Hello World du CPU
Le GPU n'a pas exécutée sa partie du programme car il n'était pas informé. En effet, les instructions n'ont pas été copiées sur la mémoire du GPU et cela se fait grâce à la fonction cudaDeviceSynchronize qu'il faut ajouter juste après l'instruction chevron:
...
cuda_hello<<<1,1>>>();
cudaDeviceSynchronize();
...
On a bien le résultat attendu:
Hello World du CPU Hello World du GPU