#include <stdio.h>
|
#include <stdlib.h>
|
#include <CL/cl.h>
|
|
const int ARRAY_SIZE = 1000;
|
/*
|
1. ´´½¨Æ½Ì¨
|
2. ´´½¨É豸
|
3. ¸ù¾ÝÉ豸´´½¨ÉÏÏÂÎÄ
|
*/
|
cl_context CreateContext(cl_device_id* device) {
|
cl_int errNum;
|
cl_uint numPlateforms;
|
cl_platform_id firstPlatformId;
|
cl_context context = NULL;
|
errNum = clGetPlatformIDs(1, &firstPlatformId, &numPlateforms);
|
|
if (errNum != CL_SUCCESS || numPlateforms <= 0) {
|
printf("Failed to find any OpenCL platforms.\n");
|
return NULL;
|
}
|
errNum = clGetDeviceIDs(firstPlatformId, CL_DEVICE_TYPE_GPU, 1, device, NULL);
|
if (errNum != CL_SUCCESS) {
|
printf("There is no GPU , trying CPU...\n");
|
errNum = clGetDeviceIDs(firstPlatformId, CL_DEVICE_TYPE_CPU, 1, device, NULL);
|
|
}
|
if (errNum != CL_SUCCESS) {
|
printf("There is NO CPU or GPU\n");
|
return NULL;
|
}
|
context = clCreateContext(NULL, 1, device, NULL, NULL, &errNum);
|
if (errNum != CL_SUCCESS) {
|
printf("Create context error\n");
|
return NULL;
|
}
|
return context;
|
}
|
/*
|
@ ÔÚÉÏÏÂÎÄ¿ÉÓõĵÚÒ»¸öÉ豸Öд´½¨ÃüÁî¶ÓÁÐ
|
*/
|
|
cl_command_queue CreateCommandQueue(cl_context context, cl_device_id device) {
|
cl_int errNum;
|
cl_command_queue commandQueue = NULL;
|
//commandQueue = clCreateCommandQueue(context, device, 0, NULL);
|
// OpenCL 2.0 µÄÓ÷¨
|
commandQueue = clCreateCommandQueueWithProperties(context, device, 0, NULL);
|
if (commandQueue == NULL) {
|
printf("Failed to create commandQueue for device 0\n");
|
return NULL;
|
}
|
return commandQueue;
|
}
|
|
char* ReadKernelSourceFile(const char* filename, size_t* length) {
|
FILE* file = NULL;
|
size_t sourceLenth;
|
char* sourceString;
|
int ret;
|
fopen_s(&file, filename, "rb");
|
|
if (file == NULL) {
|
printf("%s at %d : Can't open %s \n", __FILE__, __LINE__ - 2, filename);
|
return NULL;
|
}
|
//ÖØ¶¨Î»µ½Îļþĩβ
|
fseek(file, 0, SEEK_END);
|
sourceLenth = ftell(file);
|
//ÖØ¶¨Î»µ½Îļþ¿ªÍ·
|
fseek(file, 0, SEEK_SET);
|
sourceString = (char*)malloc(sourceLenth + 1);
|
sourceString[0] = '\0';
|
ret = fread(sourceString, sourceLenth, 1, file);
|
if (ret == 0) {
|
printf("%s at %d : Cant't read source %s\n", __FILE__, __LINE__ - 2, filename);
|
return NULL;
|
}
|
fclose(file);
|
if (length != 0) {
|
*length = sourceLenth;
|
}
|
sourceString[sourceLenth] = '\0';
|
return sourceString;
|
|
|
}
|
cl_program CreateProgram(cl_context context, cl_device_id device, const char* filename) {
|
cl_int errNum;
|
cl_program program;
|
//¼Ç¼´óСµÄÊý¾ÝÀàÐÍ
|
size_t program_length;
|
char* const source = ReadKernelSourceFile(filename, &program_length);
|
program = clCreateProgramWithSource(context, 1, (const char**)&source, NULL, NULL);
|
|
if (program == NULL) {
|
printf("Failed to creae CL program from source.\n");
|
return NULL;
|
}
|
errNum = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
|
if (errNum != CL_SUCCESS) {
|
char buildLog[16384];
|
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, sizeof(buildLog), buildLog, NULL);
|
printf("Error in kernel : %s \n", buildLog);
|
clReleaseProgram(program);
|
return NULL;
|
}
|
return program;
|
}
|
/*
|
@ ´´½¨ÄÚ´æ¶ÔÏó
|
*/
|
bool CreateMemObjects(cl_context context, cl_mem memObjects[3], float* a, float* b) {
|
memObjects[0] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(float) * ARRAY_SIZE, a, NULL);
|
memObjects[1] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(float) * ARRAY_SIZE, b, NULL);
|
memObjects[2] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float) * ARRAY_SIZE, NULL, NULL);
|
if (memObjects[0] == NULL || memObjects[1] == NULL || memObjects[2] == NULL) {
|
printf("Error creating memeory objects.\n");
|
return false;
|
|
}
|
return true;
|
}
|
/*
|
@ Çå³þOpenCL×ÊÔ´
|
*/
|
void CleanUp(cl_context context, cl_command_queue commandQueue, cl_program program, cl_kernel kernel, cl_mem memObjects[3]) {
|
for (int i = 0; i < 3; i++) {
|
if (memObjects[i] != 0) {
|
clReleaseMemObject(memObjects[i]);
|
}
|
}
|
|
if (commandQueue != 0) {
|
clReleaseCommandQueue(commandQueue);
|
}
|
if (kernel != 0) {
|
clReleaseKernel(kernel);
|
}
|
if (program != 0) {
|
clReleaseProgram(program);
|
}
|
if (context != 0) {
|
clReleaseContext(context);
|
}
|
}
|
|
/*mainº¯Êý*/
|
int main__(int argc, char** agrv) {
|
cl_context context = 0;
|
cl_command_queue commandQueue = 0;
|
cl_program program = 0;
|
cl_device_id device = 0;
|
cl_kernel kernel = 0;
|
cl_mem memObjects[3] = { 0,0,0 };
|
cl_int errNum;
|
//´´½¨OpenCLÉÏÏÂÎÄ
|
context = CreateContext(&device);
|
if (context == NULL) {
|
printf("Failed to create OpenCL context\n");
|
return 1;
|
}
|
//»ñµÃOpenCLÉ豸£¬²¢´´½¨ÃüÁî¶ÓÁÐ
|
commandQueue = CreateCommandQueue(context, device);
|
if (commandQueue == NULL) {
|
CleanUp(context, commandQueue, program, kernel, memObjects);
|
return 1;
|
}
|
//´´½¨OpenCL³ÌÐò
|
program = CreateProgram(context, device, "kernel.cl");
|
if (program == NULL) {
|
CleanUp(context, commandQueue, program, kernel, memObjects);
|
return 1;
|
}
|
kernel = clCreateKernel(program, "vector_add", NULL);
|
if (kernel == NULL) {
|
printf("Failed to create kernel\n");
|
CleanUp(context, commandQueue, program, kernel, memObjects);
|
return 1;
|
|
}
|
//´´½¨OpenCLÄÚ´æ¶ÔÏó
|
float result[ARRAY_SIZE];
|
float a[ARRAY_SIZE];
|
float b[ARRAY_SIZE];
|
for (int i = 0; i < ARRAY_SIZE; i++) {
|
a[i] = (float)i;
|
b[i] = (float)(i * 2);
|
}
|
if (!CreateMemObjects(context, memObjects, a, b)) {
|
CleanUp(context, commandQueue, program, kernel, memObjects);
|
return 1;
|
}
|
//ÉèÖÃÄں˲ÎÊý
|
errNum = clSetKernelArg(kernel, 0, sizeof(cl_mem), &memObjects[0]);
|
errNum |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &memObjects[1]);
|
errNum |= clSetKernelArg(kernel, 2, sizeof(cl_mem), &memObjects[2]);
|
|
if (errNum != CL_SUCCESS) {
|
printf("Error setting kernel arguments.\n");
|
CleanUp(context, commandQueue, program, kernel, memObjects);
|
return 1;
|
}
|
size_t globalWorkSize[1] = { ARRAY_SIZE };
|
size_t localWorkSize[1] = { 1 };
|
//Ö´ÐÐÄÚºË
|
errNum = clEnqueueNDRangeKernel(commandQueue, kernel, 1, NULL, globalWorkSize, localWorkSize, 0, NULL, NULL);
|
if (errNum != CL_SUCCESS) {
|
printf("Error queueing kernel for execution\n");
|
CleanUp(context, commandQueue, program, kernel, memObjects);
|
return 1;
|
}
|
//½«¼ÆËãµÄ½á¹û¿½±´µ½Ö÷»úÉÏ
|
errNum = clEnqueueReadBuffer(commandQueue, memObjects[2], CL_TRUE, 0, ARRAY_SIZE * sizeof(float), result, 0, NULL, NULL);
|
if (errNum != CL_SUCCESS) {
|
printf("Error reading result buffer.\n");
|
CleanUp(context, commandQueue, program, kernel, memObjects);
|
return 1;
|
}
|
for (int i = 0; i < ARRAY_SIZE; i++) {
|
printf("i=%d:%f\n", i, result[i]);
|
}
|
printf("Executed program succesfully\n");
|
CleanUp(context, commandQueue, program, kernel, memObjects);
|
return 0;
|
}
|