/******************************************************************** //--cambine:helper function for OpenCL //--programmer: Jianbin Fang //--date: 27/12/2010 ********************************************************************/ #ifndef _CL_HELPER_ #define _CL_HELPER_ #include #include #include #include #include #include using std::string; using std::ifstream; using std::cerr; using std::endl; using std::cout; #define PROFILE_ #ifdef PROFILE_ double TE; //: total execution time; double CC; //: Context creation time; double CR; //: Context release time; double MA; //: GPU memory allocation time; double MF; //: GPU memory free time; double H2D; //: the time to transfer data from host to device; double D2H; //: the time to transfer data from device to host; double D2D; //: the time to transfer data from device to device; double KE; //: the kernel execution time double KC; //: the kernel compilation time #endif //#pragma OPENCL EXTENSION cl_nv_compiler_options:enable #define WORK_DIM 2 //work-items dimensions /*------------------------------------------------------------ @struct: the structure of device properties @date: 24/03/2011 ------------------------------------------------------------*/ struct _clDeviceProp{ /*CL_DEVICE_ADDRESS_BITS CL_DEVICE_AVAILABLE CL_DEVICE_COMPILER_AVAILABLE CL_DEVICE_ENDIAN_LITTLE CL_DEVICE_ERROR_CORRECTION_SUPPORT CL_DEVICE_EXECUTION_CAPABILITIES CL_DEVICE_EXTENSIONS CL_DEVICE_GLOBAL_MEM_CACHE_SIZE CL_DEVICE_GLOBAL_MEM_CACHE_TYPE CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE CL_DEVICE_GLOBAL_MEM_SIZE CL_DEVICE_IMAGE_SUPPORT CL_DEVICE_IMAGE2D_MAX_HEIGHT CL_DEVICE_IMAGE2D_MAX_WIDTH CL_DEVICE_IMAGE3D_MAX_DEPTH CL_DEVICE_IMAGE3D_MAX_HEIGHT CL_DEVICE_IMAGE3D_MAX_WIDTH CL_DEVICE_LOCAL_MEM_SIZE CL_DEVICE_LOCAL_MEM_TYPE CL_DEVICE_MAX_CLOCK_FREQUENCY CL_DEVICE_MAX_COMPUTE_UNITS CL_DEVICE_MAX_CONSTANT_ARGS CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE CL_DEVICE_MAX_MEM_ALLOC_SIZE CL_DEVICE_MAX_PARAMETER_SIZE CL_DEVICE_MAX_READ_IMAGE_ARGS CL_DEVICE_MAX_SAMPLERS CL_DEVICE_MAX_WORK_GROUP_SIZE CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS CL_DEVICE_MAX_WORK_ITEM_SIZES CL_DEVICE_MAX_WRITE_IMAGE_ARGS CL_DEVICE_MEM_BASE_ADDR_ALIGN CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE CL_DEVICE_NAME CL_DEVICE_PLATFORM CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT CL_DEVICE_PROFILE CL_DEVICE_PROFILING_TIMER_RESOLUTION CL_DEVICE_QUEUE_PROPERTIES CL_DEVICE_SINGLE_FP_CONFIG CL_DEVICE_TYPE CL_DEVICE_VENDOR_ID CL_DEVICE_VENDOR CL_DEVICE_VERSION CL_DRIVER_VERSION*/ char device_name[100]; }; struct oclHandleStruct{ cl_context context; cl_device_id *devices; cl_command_queue queue; cl_program program; cl_int cl_status; std::string error_str; std::vector kernel; cl_mem pinned_mem_out; cl_mem pinned_mem_in; }; struct oclHandleStruct oclHandles; char kernel_file[100] = "Kernels.cl"; int total_kernels = 2; string kernel_names[2] = {"memset_kernel", "pgain_kernel"}; int work_group_size = 256; int device_id_inused = 0; //deviced id used (default : 0) int number_devices = 0; double gettime() { struct timeval t; gettimeofday(&t,NULL); return t.tv_sec+t.tv_usec*1e-6; } /*------------------------------------------------------------ @function: select device to use @params: size: the index of device to be used @return: NULL @date: 24/03/2011 ------------------------------------------------------------*/ void _clSetDevice(int idx) throw(string){ if(idx>(number_devices-1)) throw(string(":invalid device ID:")); device_id_inused = idx; } /*------------------------------------------------------------ @function: get device properties indexed by 'idx' @params: idx: device index prop: output properties @return: prop @date: 24/03/2011 ------------------------------------------------------------*/ void _clGetDeviceProperties(int idx, _clDeviceProp *prop) throw(string){ oclHandles.cl_status= clGetDeviceInfo(oclHandles.devices[idx], CL_DEVICE_NAME, 100, prop->device_name, NULL); #ifdef ERRMSG if(oclHandles.cl_status != CL_SUCCESS){ oclHandles.error_str = "exception in _clGetDeviceProperties-> "; switch(oclHandles.cl_status){ case CL_INVALID_DEVICE: oclHandles.error_str += "CL_INVALID_DEVICE"; break; case CL_INVALID_VALUE: oclHandles.error_str += "CL_INVALID_VALUE"; break; default: oclHandles.error_str += "unknown reasons"; break; } throw(oclHandles.error_str); } #endif } /* * Converts the contents of a file into a string */ string FileToString(const string fileName){ ifstream f(fileName.c_str(), ifstream::in | ifstream::binary); try{ size_t size; char* str; string s; if(f.is_open()){ size_t fileSize; f.seekg(0, ifstream::end); size = fileSize = f.tellg(); f.seekg(0, ifstream::beg); str = new char[size+1]; if (!str) throw(string("Could not allocate memory")); f.read(str, fileSize); f.close(); str[size] = '\0'; s = str; delete [] str; return s; } } catch(std::string msg){ cerr << "Exception caught in FileToString(): " << msg << endl; if(f.is_open()) f.close(); } catch(...){ cerr << "Exception caught in FileToString()" << endl; if(f.is_open()) f.close(); } string errorMsg = "FileToString()::Error: Unable to open file " + fileName; throw(errorMsg); } /*------------------------------------------------------------ @function: Read command line parameters @params: NULL @return: @date: 24/03/2011 ------------------------------------------------------------*/ char device_type[3]; static int platform_idx; static int device_idx = 0; void _clCmdParams(int argc, char* argv[]){ for (int i = 0; i < argc; ++i){ switch (argv[i][1]){ case 't': //--t stands for device type if (++i < argc){ sscanf(argv[i], "%s", device_type); } else{ std::cerr << "Could not read argument after option " << argv[i-1] << std::endl; throw; } break; case 'p': //--p stands for platform id if (++i < argc){ sscanf(argv[i], "%d", &platform_idx); } else{ std::cerr << "Could not read argument after option " << argv[i-1] << std::endl; throw; } break; case 'd': //--d stands for device id if (++i < argc){ sscanf(argv[i], "%d", &device_idx); } else{ std::cerr << "Could not read argument after option " << argv[i-1] << std::endl; throw; } break; default: ; } } } /*------------------------------------------------------------ @function: Initlize CL objects @params: device_id: device id device_type: the types of devices, e.g. CPU, GPU, ACCERLERATOR,... (1) -t cpu/gpu/acc -d 0/1/2/... (2) -t cpu/gpu/acc [-d 0] (3) [-t default] -d 0/1/2/... (4) NULL [-d 0] @return: @description: there are 5 steps to initialize all the OpenCL objects needed, @revised: get the number of devices and devices have no relationship with context @date: 24/03/2011 ------------------------------------------------------------*/ void _clInit(int platform_idx, int device_idx, string device_type)throw(string){ #ifdef PROFILE_ TE = 0; CC = 0; CR = 0; MA = 0; MF = 0; H2D = 0; D2H = 0; D2D = 0; KE = 0; KC = 0; #endif int DEVICE_ID_INUSED = 0; _clDeviceProp prop; #ifdef PROFILE_ double t1 = gettime(); #endif cl_int resultCL; oclHandles.context = NULL; oclHandles.devices = NULL; oclHandles.queue = NULL; oclHandles.program = NULL; cl_uint deviceListSize; //----------------------------------------------- //--cambine-1: find the available platforms and select one cl_uint numPlatforms; cl_platform_id targetPlatform = NULL; resultCL = clGetPlatformIDs(0, NULL, &numPlatforms); if (resultCL != CL_SUCCESS) throw (string("InitCL()::Error: Getting number of platforms (clGetPlatformIDs)")); //printf("number of platforms:%d\n",numPlatforms); //by cambine #ifdef DEV_INFO std::cout<<"--cambine: number of platforms: "< 0)) throw (string("InitCL()::Error: No platforms found (clGetPlatformIDs)")); cl_platform_id* allPlatforms = (cl_platform_id*) malloc(numPlatforms * sizeof(cl_platform_id)); resultCL = clGetPlatformIDs(numPlatforms, allPlatforms, NULL); if (resultCL != CL_SUCCESS) throw (string("InitCL()::Error: Getting platform ids (clGetPlatformIDs)")); // Select the target platform. printf("DEBUG %d \n", platform_idx); targetPlatform = allPlatforms[platform_idx]; for (int i = 0; i < numPlatforms; i++) { char pbuff[128]; resultCL = clGetPlatformInfo( allPlatforms[i], CL_PLATFORM_VENDOR, sizeof(pbuff), pbuff, NULL); if (resultCL != CL_SUCCESS) throw (string("InitCL()::Error: Getting platform info (clGetPlatformInfo)")); //printf("vedor is %s\n",pbuff); #ifdef DEV_INFO std::cout<<"--cambine: vedor is: "< clGetDeviceIDs -> CPU")); } } if(device_type.compare("gpu")==0){ oclHandles.cl_status = clGetDeviceIDs(targetPlatform, CL_DEVICE_TYPE_GPU, 0, NULL, &deviceListSize); if(oclHandles.cl_status!=CL_SUCCESS){ throw(string("exception in _clInit -> clGetDeviceIDs -> GPU")); } } if(device_type.compare("acc")==0){ oclHandles.cl_status = clGetDeviceIDs(targetPlatform, CL_DEVICE_TYPE_ACCELERATOR, 0, NULL, &deviceListSize); if(oclHandles.cl_status!=CL_SUCCESS){ throw(string("exception in _clInit -> clGetDeviceIDs -> ACCELERATOR")); } } } else{ oclHandles.cl_status = clGetDeviceIDs(targetPlatform, CL_DEVICE_TYPE_ALL, 0, NULL, &deviceListSize); if(oclHandles.cl_status!=CL_SUCCESS){ throw(string("exception in _clInit -> clGetDeviceIDs -> ALL")); } } if (deviceListSize == 0) throw(string("InitCL()::Error: No devices found.")); #ifdef DEV_INFO std::cout<<"--cambine: number of device="< clGetDeviceIDs -> CPU ->2")); } } if(device_type.compare("gpu")==0){ oclHandles.cl_status = clGetDeviceIDs(targetPlatform, CL_DEVICE_TYPE_GPU, deviceListSize, oclHandles.devices, NULL); if(oclHandles.cl_status!=CL_SUCCESS){ throw(string("exception in _clInit -> clGetDeviceIDs -> GPU -> 2")); } } if(device_type.compare("acc")==0){ oclHandles.cl_status = clGetDeviceIDs(targetPlatform, CL_DEVICE_TYPE_ACCELERATOR, deviceListSize, oclHandles.devices, NULL); if(oclHandles.cl_status!=CL_SUCCESS){ throw(string("exception in _clInit -> clGetDeviceIDs -> ACCELERATOR -> 2")); } } } else{ oclHandles.cl_status = clGetDeviceIDs(targetPlatform, CL_DEVICE_TYPE_ALL, deviceListSize, oclHandles.devices, NULL); if(oclHandles.cl_status!=CL_SUCCESS){ throw(string("exception in _clInit -> clGetDeviceIDs -> ALL -> 2")); } } if(device_idx!=0){ if(device_idx>(deviceListSize-1)) throw(string("Invalidate device id")); DEVICE_ID_INUSED = device_idx; } _clGetDeviceProperties(DEVICE_ID_INUSED, &prop); std::cout<<"--cambine: device name="< clGetProgramInfo-2")); } std::cout<<"--cambine:"< clGetProgramInfo-3")); } for(int i=0;i getting resource information")); } build_log = (char *)malloc(ret_val_size+1); oclHandles.cl_status = clGetProgramBuildInfo(oclHandles.program, oclHandles.devices[DEVICE_ID_INUSED], CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL); if(oclHandles.cl_status!=CL_SUCCESS){ throw(string("exceptions in _InitCL -> getting resources allocation information-2")); } build_log[ret_val_size] = '\0'; std::cout<<"--cambine:"<