From 67a5e3d825fde17b7b00906ce42b0bd8cafebc4e Mon Sep 17 00:00:00 2001 From: admin <weikou2014> Date: 星期四, 18 八月 2022 18:22:14 +0800 Subject: [PATCH] '完善' --- ConsoleApplication/OpenclTest.cpp | 617 ++++++++++++++++++------------------------------------- 1 files changed, 206 insertions(+), 411 deletions(-) diff --git a/ConsoleApplication/OpenclTest.cpp b/ConsoleApplication/OpenclTest.cpp index 673c0b4..ee51a5f 100644 --- a/ConsoleApplication/OpenclTest.cpp +++ b/ConsoleApplication/OpenclTest.cpp @@ -1,431 +1,226 @@ -#include<stdio.h> -#include<stdlib.h> -#include<iostream> -#include<CL/cl.h> -#include <chrono> -#include "OpenCLExcuter.h" -#include "ImgUtil.h" -using namespace std; -void printDevice(); -uchar* createDemoData(int line); -uchar* createTemplateData(int line); +#include <stdio.h> +#include <stdlib.h> +#include <CL/cl.h> -int LINE_NUMBER = 10; -int RE = _NUMBER_L2_TOTAL_NUMBER; +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); - - -#define CHECK_ERRORS(ERR) \ - if(ERR != CL_SUCCESS){ \ - std::cerr << "OpenCL error code" << ERR << "file: " << __FILE__ << "line: " << __LINE__ << ".\nExiting..." << std::endl; \ - exit(1); \ + if (errNum != CL_SUCCESS || numPlateforms <= 0) { + printf("Failed to find any OpenCL platforms.\n"); + return NULL; } -int main1() { - //printDevice(); - //return 1; - auto starttime = std::chrono::steady_clock::now(); + 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); - cl_int error; - cl_uint num_of_platforms = 0; - cl_platform_id platforms; + } + 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_device_id devices; +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; +} - cl_context context; +char* ReadKernelSourceFile(const char* filename, size_t* length) { + FILE* file = NULL; + size_t sourceLenth; + char* sourceString; + int ret; + fopen_s(&file, filename, "rb"); - FILE* program_handle; - size_t program_size; - char* program_buffer; + 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); - size_t log_size; - char* program_log; - - char kernel_name[] = "createBuffer"; - cl_kernel kernel; - - cl_command_queue queue; - //获取平台 - error = clGetPlatformIDs(1, &platforms, &num_of_platforms); - if (error != 0) { - printf("Get platform failed!"); - return -1; + if (program == NULL) { + printf("Failed to creae CL program from source.\n"); + return NULL; } - //获取设备 - error = clGetDeviceIDs(platforms, CL_DEVICE_TYPE_GPU, 1, &devices, NULL); - if (error != 0) { - printf("Get device failed!"); - return -1; + 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]); + } } - std::cout << " 获取设备:" << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - starttime).count() << std::endl; - - //创建上下文 - context = clCreateContext(NULL, 1, &devices, NULL, NULL, &error); - if (error != 0) { - printf("Creat context failed!"); - return -1; + if (commandQueue != 0) { + clReleaseCommandQueue(commandQueue); } - std::cout << " 创建上下文:" << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - starttime).count() << std::endl; - //创建程序;注意要用"rb" - fopen_s(&program_handle,"kernel.cl", "rb"); - if (program_handle == NULL) { - printf("The kernle can not be opened!"); - return -1; - } - fseek(program_handle, 0, SEEK_END); - program_size = ftell(program_handle); - rewind(program_handle); - - program_buffer = (char*)malloc(program_size + 1); - program_buffer[program_size] = '\0'; - error = fread(program_buffer, sizeof(char), program_size, program_handle); - if (error == 0) { - printf("Read kernel failed!"); - return -1; - } - fclose(program_handle); - program = clCreateProgramWithSource(context, 1, (const char**)&program_buffer, - &program_size, &error); - if (error < 0) { - printf("Couldn't create the program!"); - return -1; - } - //编译程序 - error = clBuildProgram(program, 1, &devices, NULL, NULL, NULL); - if (error < 0) { - //确定日志文件的大小 - clGetProgramBuildInfo(program, devices, CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size); - program_log = (char*)malloc(log_size + 1); - program_log[log_size] = '\0'; - //读取日志 - clGetProgramBuildInfo(program, devices, CL_PROGRAM_BUILD_LOG, - log_size + 1, program_log, NULL); - printf("%s\n", program_log); - free(program_log); - return -1; - } - free(program_buffer); - - //创建命令队列 - queue = clCreateCommandQueue(context, devices, CL_QUEUE_PROFILING_ENABLE, &error); - if (error < 0) { - printf("Coudn't create the command queue"); - return -1; - } - //----------程序正文开始--------- - - for (int n = 0;n < 100;n++) - { - - auto startexectime = std::chrono::steady_clock::now(); - - - - //创建内核 - kernel = clCreateKernel(program, "createBuffer", &error); - if (kernel == NULL) { - printf("Couldn't create kernel!\n"); - return -1; - } - //初始化参数 - const int size = 70000; - float result[size]; - float a_in[size]; - float b_in[size]; - for (int i = 0; i < size; i++) { - a_in[i] = i+n; - b_in[i] = i * 2.0; - } - //创建缓存对象 - cl_mem memObject1 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(float) * size, a_in, &error); - if (error < 0) { - printf("Creat memObject1 failed!\n"); - return -1; - } - cl_mem memObject2 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, - sizeof(float) * size, b_in, &error); - if (error < 0) { - printf("Creat memObject2 failed!\n"); - return -1; - } - cl_mem memObject3 = clCreateBuffer(context, CL_MEM_WRITE_ONLY, - sizeof(float) * size, NULL, &error); - if (error < 0) { - printf("Creat memObject3 failed!\n"); - return -1; - } - //设置内核参数 - error = clSetKernelArg(kernel, 0, sizeof(cl_mem), &memObject1); - error |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &memObject2); - error |= clSetKernelArg(kernel, 2, sizeof(cl_mem), &memObject3); - if (error != CL_SUCCESS) { - printf("Error setting kernel arguments!\n"); - return -1; - } - //执行内核 - size_t globalWorkSize[1] = { size }; - size_t localWorkSize[1] = { 1 }; - - const int work_dim = 2; - - error = clEnqueueNDRangeKernel(queue, kernel, work_dim, NULL, globalWorkSize, - localWorkSize, 0, NULL, NULL); - if (error != CL_SUCCESS) { - printf("Error queuing kernel for execution!\n"); - return -1; - } - - //读取执行结果 - error = clEnqueueReadBuffer(queue, memObject3, CL_TRUE, 0, size * sizeof(float), - result, 0, NULL, NULL); - if (error != CL_SUCCESS) { - printf("Error reading result buffer!\n"); - return -1; - } - //显示结果 - for (int i = 0; i < 2; i++) { - printf("%f ", result[i]); - } - + if (kernel != 0) { clReleaseKernel(kernel); - clReleaseMemObject(memObject1); - clReleaseMemObject(memObject2); - clReleaseMemObject(memObject3); - - - std::cout << " 执行结束:" << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - startexectime).count() << std::endl; } + 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]); - - //释放资源 - clReleaseDevice(devices); - clReleaseContext(context); - clReleaseProgram(program); - clReleaseCommandQueue(queue); - - std::cout << " 耗时:" << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - starttime).count() << std::endl; + 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; } - - -int main3() { - ImgUtil::init(); - OpenCLExcuter* op = new OpenCLExcuter(); - int dataCount = 100; - - - int rows = 8* dataCount; - int cols = 5 * LINE_NUMBER * RE; - uchar* b_in = createTemplateData(dataCount); - uchar* a_in = createDemoData(dataCount); - - //printf("输入1: \n"); - for (int r = 0;r < rows;r++) { - for (int c = 0;c < cols;c++) { - // printf("%d ", a_in[r*cols+c]); - } - // printf("\n"); - } - - //printf("输入2: \n"); - for (int r = 0;r < rows;r++) { - for (int c = 0;c < cols;c++) { - // printf("%d ", b_in[r * cols + c]); - } - //printf("\n"); - } - - /* - int rows = 10; - int cols = 10; - uchar* b_in = (uchar*)malloc(sizeof(uchar*)*400); - uchar* a_in = (uchar*)malloc(sizeof(uchar*) * 400); - for (int i = 0;i < 400;i++) { - b_in[i] = i; - a_in[i] = i + 1; - } - */ - - op->init(); - for (int i = 0;i < 100;i++) - { - op->recognition_numbers(a_in, b_in, rows, cols ,_NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, _NUMBER_L2_TOTAL_NUMBER); - } - op->destory(); - - return 1; -} - -uchar* createDemoData(int line) { - unsigned char* data = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_L2_HEIGHT * line) * 5 * LINE_NUMBER * RE); - int outLineDataCount = 8 * 5 * LINE_NUMBER * RE; - int inLineDataCount = 5 * LINE_NUMBER * RE; - for (int l = 0;l < line;l++) - { - int outLineCount = outLineDataCount * l; - for (int re = 0;re < RE;re++) { - - - - for (int n = 0;n < LINE_NUMBER;n++) - { - for (int r = 0;r < 8;r++) { - int intLineCount = inLineDataCount * r; - - for (int c = 0;c < 5;c++) { - uchar value = ImgUtil::NUMS_LEVEL2[re%10].data.ptr(r)[c]; - int index = outLineCount; - index += intLineCount; - int x = re * LINE_NUMBER * 5 + n * 5 + c; - index += x; - data[index] = value > 40 ? 1 : 0; - } - } - } - } - } - return data; -} - -uchar* createTemplateData(int line) { - unsigned char* data = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_L2_HEIGHT * line) * _NUMBER_L2_WIDTH * LINE_NUMBER * RE); - int outLineDataCount = _NUMBER_L2_HEIGHT * _NUMBER_L2_WIDTH * LINE_NUMBER * RE; - int inLineDataCount = _NUMBER_L2_WIDTH * LINE_NUMBER * RE; - for (int l = 0;l < line;l++) - { - int outLineCount = outLineDataCount * l; - for (int re = 0;re < RE;re++) { - for (int n = 0;n < LINE_NUMBER;n++) - { - for (int r = 0;r < _NUMBER_L2_HEIGHT;r++) { - int intLineCount = inLineDataCount * r; - - for (int c = 0;c < _NUMBER_L2_WIDTH;c++) { - uchar value = ImgUtil::NUMS_LEVEL2[n].data.ptr(r)[c]; - int index = outLineCount; - index += intLineCount; - int x = re * LINE_NUMBER * _NUMBER_L2_WIDTH + n * _NUMBER_L2_WIDTH + c; - index += x; - data[index] = value > 40 ? 1 : 0; - } - } - } - } - } - return data; -} - - -void printDevice() { - - cl_int err = CL_SUCCESS; - - // 1. 获取当前设备所有支持OpenCL的平台的数量 - cl_uint num_of_platforms = 0; - err = clGetPlatformIDs(0, 0, &num_of_platforms); - CHECK_ERRORS(err); - - // 2. 获取当前设备所有支持OpenCL的平台的信息 - cl_platform_id* platforms = new cl_platform_id[num_of_platforms]; - err = clGetPlatformIDs(num_of_platforms, platforms, 0); - CHECK_ERRORS(err); - - cl_char platform_names[10][50]; - // 3. 打印平台信息 - cout << "平台信息:\n"; - for (cl_uint i = 0; i < num_of_platforms; i++) - { - // 获取平台字符串的长度 - size_t platform_name_length = 0; - err = clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, 0, 0, &platform_name_length); - CHECK_ERRORS(err); - - // 获取平台字符串 - char* platform_name = new char[platform_name_length]; - err = clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, platform_name_length, platform_name, 0); - CHECK_ERRORS(err); - - cout << " [" << i << "] " << platform_name << endl; - - // 备份platform name - if (i < 10) { - memset(platform_names[i], 0, 50); - memcpy(platform_names[i], platform_name, platform_name_length); - } - - delete[] platform_name; - } - - // 4. 查询各平台设备数量 - struct { - cl_device_type type; - const char* name; - cl_uint count; - }devices[] = { - {CL_DEVICE_TYPE_GPU, "CL_DEVICE_TYPE_GPU", 0}, // GPU - {CL_DEVICE_TYPE_CPU, "CL_DEVICE_TYPE_CPU", 0}, // CPU - {CL_DEVICE_TYPE_ACCELERATOR, "CL_DEVICE_TYPE_ACCELERATOR", 0} // 加速器 - }; - - // 5. 遍历查询各个平台下拥有的设备数量 - for (cl_int j = 0; j < num_of_platforms; j++) { - cl_platform_id platform = platforms[j]; - cout << "\nplatform:" << platform_names[j] << endl; - - // 6. 遍历查询GPU、CPU、ACCELERATOR设备的数量 - for (cl_int i = 0; i < (sizeof(devices) / sizeof(devices[0])); i++) - { - err = clGetDeviceIDs(platform, devices[i].type, 0, 0, &devices[i].count); - if (err == CL_DEVICE_NOT_FOUND) { - devices[i].count = 0; - err = CL_SUCCESS; - } - CHECK_ERRORS(err); - - cout << "\tdevices:" << devices[i].name - << "\tcount:" << devices[i].count; - - if (devices[i].count != 0) { - // 7. 遍历查询GPU、CPU、ACCELERATOR 所有设备的信息 - cl_device_id* device = new cl_device_id[devices[i].count]; - err = clGetDeviceIDs(platform, devices[i].type, devices[i].count, device, 0); - - cout << "\t\tdevice name:"; - for (cl_int k = 0; k < devices[i].count; k++) - { - // 8. 获取和打印各个设备的name - size_t length = 0; - cl_device_id each_device = device[k]; - err = clGetDeviceInfo(each_device, CL_DEVICE_NAME, 0, 0, &length); - CHECK_ERRORS(err); - - char* value = new char[length]; - err = clGetDeviceInfo(each_device, CL_DEVICE_NAME, length, value, 0); - CHECK_ERRORS(err); - cout << value << " "; - - // 9. 获取和打印各个设备的version - err = clGetDeviceInfo(each_device, CL_DEVICE_VERSION, 0, 0, &length); - CHECK_ERRORS(err); - - char* version = new char[length]; - err = clGetDeviceInfo(each_device, CL_DEVICE_VERSION, length, version, 0); - CHECK_ERRORS(err); - cout << version << " "; - - delete[] value; - delete[] version; - } - - delete[] device; - } - cout << endl; - } - } - - delete[] platforms; -} \ No newline at end of file -- Gitblit v1.8.0