#include #include #include 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; }