Premiers pas

 

#include<stdio.h>
#include<CL/cl.h>
#include <stdlib.h>
#include <string.h>

char *loadfile(const char *filename)
{
long   len ;
FILE * file  ;
char * buffer ;

file = fopen(filename, »r ») ;
if (file==NULL) {
fprintf(stderr, »*** failed to open file ‘%s’\n »,filename) ;
return NULL ;
}

/* Get the file length */
fseek(file,0L,SEEK_END) ;
len = ftell(file) ;

/* 640K should be enough for everyone */
if (len<=0 || len>640*1024) {
fprintf(stderr, »*** unexpected file length %ld for ‘%s’ \n »,len, filename) ;
}

/* allocate and load the file */
buffer = (char*) malloc(len+1);
fseek(file,0L,SEEK_SET) ;
fread(buffer,len,1,file) ;
buffer[len] = ‘\0’ ;

return buffer ;
}

void erreur(char *s)
{
printf(« Erreur %s\n »,s);
exit(0);
}

int main(int argc, char *argv[])
{

unsigned char j;
unsigned int taille_tab;

// Declarations propres a OpenCL

cl_platform_id id_plateforme ;
cl_uint nb_plateformes, nb_devices ;
cl_int bprogram, kernelarg, oclErr ;
cl_device_id id_device[2] ;
cl_context context ;
cl_command_queue queue ;
cl_program program ;
cl_kernel kernel ;
cl_mem cltableau, clresultat ;
char *source ;

unsigned int i ;
int *tableau ;
unsigned long *resultat;
size_t cltaille, cltaille2 ;

taille_tab=atoi(argv[1]);

tableau =(int *)malloc(taille_tab*sizeof(int));
resultat=(unsigned long *)malloc(taille_tab*sizeof(unsigned long));

cltaille=taille_tab*sizeof(cl_int);
cltaille2=taille_tab*sizeof(cl_ulong);

if (argc < 2)
erreur(« Usage: ./a.out taille »);

memset(resultat,0,taille_tab*sizeof(unsigned long));

for (i = 0; i < taille_tab; i++)
tableau[i] = i;

if (clGetPlatformIDs(1,&id_plateforme,&nb_plateformes) != CL_SUCCESS)
erreur(« clGetPlatformIDs »);

clGetDeviceIDs(id_plateforme,CL_DEVICE_TYPE_GPU,0,NULL,&nb_devices);
if (clGetDeviceIDs(id_plateforme,CL_DEVICE_TYPE_GPU,nb_devices,id_device,NULL) != CL_SUCCESS)
erreur(« clGetDeviceIDs »);

if ((context = clCreateContext(NULL,1,&(id_device[0]),NULL,NULL,NULL)) == NULL)
erreur(« clCreateContext »);

if ((queue = clCreateCommandQueue(context,id_device[0],CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,NULL)) == NULL)
erreur(« clCreateCommandQueue »);

source=loadfile(« plusun.cl »);

if ((program = clCreateProgramWithSource(context, 1, (const char **)&source, NULL, NULL)) == NULL)
erreur(« clCreateProgramWithSource »);

if ((bprogram = clBuildProgram(program,0,NULL,NULL,NULL,NULL)) != CL_SUCCESS)
erreur(« clBuildProgram »);

if ((kernel = clCreateKernel(program, »plusun_kernel »,NULL)) == NULL)
erreur(« clCreateKernel »);

if ((cltableau = clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR,cltaille,tableau,NULL)) == NULL)
erreur(« clCreateBuffer1 »);

if ((clresultat = clCreateBuffer(context, CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR,cltaille2,resultat,NULL)) == NULL)
erreur(« clCreateBuffer2 »);

if ((kernelarg = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void*)&cltableau)) != CL_SUCCESS)
erreur(« clSetKernelArg0 »);

if ((kernelarg = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void*)&clresultat)) != CL_SUCCESS)
erreur(« clSetKernelArg1 »);

if ((kernelarg = clSetKernelArg(kernel, 2, sizeof(cl_int), NULL)) != CL_SUCCESS)
erreur(« clSetKernelArg2 »);

const size_t global_item_size = taille_tab ;
const size_t local_item_size = 1 ;

if ((oclErr=clEnqueueNDRangeKernel(queue,kernel,1,NULL,&global_item_size,&local_item_size,0,NULL,NULL)) !=CL_SUCCESS)
erreur(« clEnqueueNDRangeKernel »);

if ((oclErr=clEnqueueReadBuffer(queue,clresultat,CL_TRUE,0,cltaille2,resultat,0,NULL,NULL)) !=CL_SUCCESS)
erreur(« clEnqueueReadBuffer »);

for (i = 0; i < taille_tab ; i++)
printf(« %d %lu\n »,tableau[i],resultat[i]);
printf(« fin\n »);

// Nettoyage

oclErr = clFlush(queue);
oclErr = clFinish(queue);
oclErr = clReleaseKernel(kernel);
oclErr = clReleaseProgram(program);
oclErr = clReleaseMemObject(cltableau);
oclErr = clReleaseMemObject(clresultat);
oclErr = clReleaseCommandQueue(queue);
oclErr = clReleaseContext(context);
free(tableau);
free(resultat);
return 0;
}

Le kernel OpenCL associé :

__kernel void plusun_kernel(__global const int *a, __global unsigned long *res, __local int *tempo)
{
int gid = get_global_id(0);
*tempo = a[gid] ;
*tempo = *tempo + 1 ;
res[gid] = *tempo ;
}

 

Lien Permanent pour cet article : https://calcul-scientifique.univ-tln.fr/2012/01/premiers-pas/