Programmation de cartes graphiques. OpenCL API + langage basé sur le C99 Conçu pour programmer des...
35
OpenCL Programmation de cartes graphiques
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,
OpenCL API + langage bas sur le C99 Conu pour programmer des
systmes parallles htrognes: CPU multi-coeur, GPU, etc. On distingue
le processeur hte des priphriques Un conteneur spcial (context)
sert dinterface entre le processeur hte et les priphriques Les
donnes et les tches (kernels) sont transfrs laide dune file
dattente (command queue)
Page 3
Un priphrique vu par OpenCL
Page 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]; }
Page 5
Comparaison: Programmation multithread void vecadd(int *C, int*
A, int *B, int N, int NP, int tid) { int ept = N/NP; // nbre
dlments par thread for(int i = tid*ept; i < (tid+1)*ept; i++) {
C[i] = A[i] + B[i]; }
Page 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]; }
Page 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
priphrique (NDRange) Un indice local unique pour chaque work-item
lintrieur dun mme workgroup.
Page 8
NDRange et Workgroups
Page 9
Connatre 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.
Page 10
Relation entre global et local get_global_id(dim) =
get_local_size(dim)*get_group_id(dim) + get_local_id(dim)
Page 11
Plateformes Une plateforme est une implmentation de OpenCL
spcifique 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
Page 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);
Page 13
Priphriques Pour chacune des plateformes (ex. NVIDIA), on peut
obtenir la liste des priphriques associs: cl_int
clGetDeviceIDs(cl_platform_id platform, cl_device_type device_type,
cl_uint num_entries, cl_device_id *devices, cl_uint
*num_devices)
Page 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);
Page 15
Contextes Un contexte est un type de conteneur permettant de
communiquer des donnes et des instructions des priphriques On
utilise la fonction: clCreateContext Le premier paramtre sert limit
la port du contexte, par exemple en spcifiant une plateforme
particulire. Le callback sert a fournir une fonction qui pourra
fournir davantage dinformation sur les erreurs se produisant tout
au long de lutilisation du contexte.
File de commandes On a dj dit quun contexte est un conteneur
permettant de communiquer avec un priphrique. On ajoute et retire
linformation dun contexte laide dune file dattente appele file de
commande (command queue). Toutes les commandes indiquant une
communication hte-priphrique commencent par clEnqueue.
Page 19
Cration 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 paramtre properties sert, entre autres, indiquer si les lments
seront pris dans lordre.
Objets mmoire Avant dtre transfrs, les donnes doivent tre
converties dans un format particulier. Il y a deux formats: Les
tampons (buffers) Les images Les tampons sont lquivalent des
tableaux en C et sont stocks de faon contigu en mmoire. Les images
sont des objets opaques et sont places en mmoire de faon optimiser
les performances.
Page 22
Cration dun tampon cl_mem clCreateBuffer( cl_context context,
cl_mem_flags flags, size_t size, void *host_ptr, cl_int
*errcode_ret) Note: Le paramtre flags sert indiquer si le tampon
est en lecture, en criture ou les deux.
Kernels Il faut distinguer le programme C de lordinateur hte du
programme C OpenCL qui sera excut sur un priphrique. Un programme C
OpenCL est une collection de fonctions appeles kernels Le type de
retour de ces fonctions doit tre void Les kernels reprsentent les
tches que lon peut ordonnancer de faon dynamique sur les
priphriques.
Page 27
Cration et excution dun kernel 1. Le code source est stock sous
la forme dune chane de caractres 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 paramtres du kernel sont affects laide de la commande
clSetKernelArg() 6. Le kernel est finalement excut laide de la
commande clEnqueueNDRangeKernel()
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.
Page 31
Affecter les paramtres cl_int clSetKernelArg ( cl_kernel
kernel, cl_uint arg_index, size_t arg_size, const void *arg_value)
Note: Les paramtres demeurent affects au kernel tant quil ny a pas
de modification explicite laide de clSetKernelArg()
Espaces dadressage Les qualificat __global: Mmoire partage par
tous les work-items du kernel. __constant: Mmoire en lecture seule
partage par tous les work-items du kernel. __local: Mmoire partage
par tous les work-items dun mme work-group. __private: Mmoire prive
pour chaque work-item.
Page 35
Espace dadressage par dfaut Pour amliorer la performance, on
utilise autant que possible la mmoire __local ou __private. Sil ny
a pas de qualificatif, les paramtres des fonctions et les variables
locales sont __private Le qualificatif des paramtres qui sont des
pointeurs doit tre spcifi et ne peut pas tre __private. Les mmoires
__private et __local ne sont pas prserves la fin de lexcution dun
work-item. La seule faon de retourner une valeur lhte est via la
mmoire __global.