La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Programmation de cartes graphiques. OpenCL API + langage basé sur le C99 Conçu pour programmer des systèmes parallèles hétérogènes: CPU multi-coeur, GPU,

Présentations similaires


Présentation au sujet: "Programmation de cartes graphiques. OpenCL API + langage basé sur le C99 Conçu pour programmer des systèmes parallèles hétérogènes: CPU multi-coeur, GPU,"— Transcription de la présentation:

1 Programmation de cartes graphiques

2 OpenCL API + langage basé sur le C99 Conçu pour programmer des systèmes parallèles hétérogènes: CPU multi-coeur, GPU, etc. On distingue le processeur hôte des périphériques Un conteneur spécial (context) sert dinterface entre le processeur hôte et les périphériques Les données et les tâches (kernels) sont transférés à laide dune file dattente (command queue)

3 Un périphérique vu par OpenCL

4 Comparaison: C standard // Addition de 2 vecteurs de taille N // void vecadd(int *C, int* A, int *B, int N) { for(int i = 0; i < N; i++) { C[i] = A[i] + B[i]; }

5 Comparaison: Programmation multithread void vecadd(int *C, int* A, int *B, int N, int NP, int tid) { int ept = N/NP; // nbre déléments par thread for(int i = tid*ept; i < (tid+1)*ept; i++) { C[i] = A[i] + B[i]; }

6 Comparaison: OpenCL __kernel void vecadd(__global int *C, __global int* A, __global int *B) { int tid = get_global_id(0); // fonction OpenCL C[tid] = A[tid] + B[tid]; }

7 Espace des indices En OpenCL, lespace des indices des processeurs peut avoir 1, 2 ou 3 dimensions. Il y a deux niveaux dindices: Un indice global unique pour chaque work-item du périphérique (NDRange) Un indice local unique pour chaque work-item à lintérieur dun même workgroup.

8 NDRange et Workgroups

9 Connaître son indice get_global_id(dim): indice globale du work-item appelant selon la dimension dim=0,1 ou 2 get_local_id(dim): indice local du work-item appelant get_group_id(dim): indice du workgroup auquel appartient le work-item appelant get_local_size(dim): taille de la dimension dim dans le workgroup du work-item appelant.

10 Relation entre global et local get_global_id(dim) = get_local_size(dim)*get_group_id(dim) + get_local_id(dim)

11 Plateformes Une plateforme est une implémentation de OpenCL spécifique à un manufacturier donné Pour obtenir la liste des plateformes: cl_int clGetPlatformIDs(cl_uint num_entries, cl_platform_id *platforms, cl_uint *num_platforms) clGetPlatformInfo pour obtenir de linformation sur une plateforme donné

12 Exemple 1 cl_int status; cl_uint numPlatforms = 0; cl_platform_id *platforms = NULL; status = clGetPlatformIDs(0, NULL, &numPlatforms); platforms = (cl_platform_id*)malloc( numPlatforms*sizeof(cl_platform_id)); status = clGetPlatformIDs(numPlatforms, platforms, NULL); char Name[1000]; clGetPlatformInfo(platforms[0], CL_PLATFORM_NAME, sizeof(Name), Name, NULL); printf("Name of platform : %s\n", Name);

13 Périphériques Pour chacune des plateformes (ex. NVIDIA), on peut obtenir la liste des périphériques associés: cl_int clGetDeviceIDs(cl_platform_id platform, cl_device_type device_type, cl_uint num_entries, cl_device_id *devices, cl_uint *num_devices)

14 Exemple 2 cl_uint numDevices = 0; cl_device_id *devices = NULL; status = clGetDeviceIDs( platforms[0], CL_DEVICE_TYPE_ALL, 0, NULL, &numDevices); devices = (cl_device_id*)malloc( numDevices*sizeof(cl_device_id)); status = clGetDeviceIDs( platforms[0], CL_DEVICE_TYPE_ALL, numDevices, devices, NULL);

15 Contextes Un contexte est un type de conteneur permettant de communiquer des données et des instructions à des périphériques On utilise la fonction: clCreateContext Le premier paramètre sert à limité la porté du contexte, par exemple en spécifiant une plateforme particulière. Le « callback » sert a fournir une fonction qui pourra fournir davantage dinformation sur les erreurs se produisant tout au long de lutilisation du contexte.

16 Contextes cl_context clCreateContext ( const cl_context_properties *properties, cl_uint num_devices, const cl_device_id *devices, void (CL_CALLBACK *pfn_notify)( const char *errinfo, const void *private_info, size_t cb, void *user_data), void *user_data, cl_int *errcode_ret)

17 Exemple 3 cl_context context = NULL; context = clCreateContext( NULL, numDevices, devices, NULL, &status);

18 File de commandes On a déjà dit quun contexte est un conteneur permettant de communiquer avec un périphérique. On ajoute et retire linformation dun contexte à laide dune file dattente appelée « file de commande » (command queue). Toutes les commandes indiquant une communication hôte-périphérique commencent par clEnqueue.

19 Création dune file de commandes cl_command_queue clCreateCommandQueue( cl_context context, cl_device_id device, cl_command_queue_properties properties, cl_int* errcode_ret) Note: Le paramètre « properties » sert, entre autres, à indiquer si les éléments seront pris dans lordre.

20 Exemple 4 cl_command_queue cmdQueue; cmdQueue = clCreateCommandQueue( context, devices[0], 0, &status);

21 Objets mémoire Avant dêtre transférés, les données doivent être converties dans un format particulier. Il y a deux formats: Les tampons (buffers) Les images Les tampons sont léquivalent des tableaux en C et sont stockés de façon contiguë en mémoire. Les images sont des objets opaques et sont placées en mémoire de façon optimiser les performances.

22 Création dun tampon cl_mem clCreateBuffer( cl_context context, cl_mem_flags flags, size_t size, void *host_ptr, cl_int *errcode_ret) Note: Le paramètre « flags » sert à indiquer si le tampon est en lecture, en écriture ou les deux.

23 Écrire dans un tampon cl_int clEnqueueWriteBuffer ( cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, // CL_TRUE pour appel bloquant size_t offset, size_t cb, const void *ptr, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event)

24 Lire dans un tampon cl_int clEnqueueReadBuffer( cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, size_t offset, size_t size, void *ptr, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event)

25 Exemple 5 cl_mem bufferA, bufferB, bufferC; bufferA = clCreateBuffer( context, CL_MEM_READ_ONLY, datasize, NULL, &status); bufferB = clCreateBuffer( context, CL_MEM_READ_ONLY, datasize, NULL, &status); bufferC = clCreateBuffer( context, CL_MEM_WRITE_ONLY, datasize, NULL, &status); status = clEnqueueWriteBuffer( cmdQueue, bufferA, CL_FALSE, 0, datasize, A, 0, NULL, NULL); status = clEnqueueWriteBuffer( cmdQueue, bufferB, CL_FALSE, 0, datasize, B, 0, NULL, NULL);

26 Kernels Il faut distinguer le programme C de lordinateur hôte du programme C OpenCL qui sera exécuté sur un périphérique. Un programme C OpenCL est une collection de fonctions appelées « kernels » Le type de retour de ces fonctions doit être void Les kernels représentent les tâches que lon peut ordonnancer de façon dynamique sur les périphériques.

27 Création et exécution dun kernel 1. Le code source est stocké sous la forme dune chaîne de caractères 2. La chaine est convertie en objet programmes à laide de la commande clCreateProgramWithSource() 3. Un objet programme est compilé à laide de la commande clBuildProgram() 4. Un kernel est obtenu à laide de la fonction 5. Les paramètres du kernel sont affectés à laide de la commande clSetKernelArg() 6. Le kernel est finalement exécuté à laide de la commande clEnqueueNDRangeKernel()

28 Création dun objet programme cl_program clCreateProgramWithSource ( cl_context context, cl_uint count, const char **strings, const size_t *lengths, cl_int *errcode_ret)

29 Compiler un objet programme cl_int clBuildProgram ( cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, void (CL_CALLBACK *pfn_notify)(cl_program program, void *user_data), void *user_data)

30 Obtenir un kernel cl_kernel clCreateKernel ( cl_program program, const char *kernel_name, cl_int *errcode_ret) Note: *kernel_name contient le nom dune fonction dans le programme source.

31 Affecter les paramètres cl_int clSetKernelArg ( cl_kernel kernel, cl_uint arg_index, size_t arg_size, const void *arg_value) Note: Les paramètres demeurent affectés au kernel tant quil ny a pas de modification explicite à laide de clSetKernelArg()

32 Exécuter un kernel cl_int clEnqueueNDRangeKernel( cl_command_queue command_queue, cl_kernel kernel, cl_uint work_dim, const size_t *global_work_offset, const size_t *global_work_size, const size_t *local_work_size, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event)

33 Organisation de la mémoire

34 Espaces dadressage Les qualificat __global: Mémoire partagée par tous les work-items du kernel. __constant: Mémoire en lecture seule partagée par tous les work-items du kernel. __local: Mémoire partagée par tous les work-items dun même work-group. __private: Mémoire privée pour chaque work-item.

35 Espace dadressage par défaut Pour améliorer la performance, on utilise autant que possible la mémoire __local ou __private. Sil ny a pas de qualificatif, les paramètres des fonctions et les variables locales sont __private Le qualificatif des paramètres qui sont des pointeurs doit être spécifié et ne peut pas être __private. Les mémoires __private et __local ne sont pas préservées à la fin de lexécution dun work-item. La seule façon de retourner une valeur à lhôte est via la mémoire __global.


Télécharger ppt "Programmation de cartes graphiques. OpenCL API + langage basé sur le C99 Conçu pour programmer des systèmes parallèles hétérogènes: CPU multi-coeur, GPU,"

Présentations similaires


Annonces Google