Cuda hello world

De The Linux Craftsman
Révision datée du 4 juin 2021 à 13:59 par Jc.forton (discussion | contributions) (Page créée avec « = 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 propo... »)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)
Aller à la navigation Aller à la recherche

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

Parallélisation