// select OpenCL devices by uint parameter void HGPU_GPU_devices_select_by_parameter_uint(HGPU_GPU_devices** devices,cl_device_info parameter,unsigned long int min_value){ unsigned int number_of_devices = HGPU_GPU_devices_get_number(*devices); if (!number_of_devices) HGPU_GPU_error(HGPU_ERROR_NO_DEVICE); cl_uint desired_devices = 0; for(unsigned int i=0; i<number_of_devices; i++){ cl_device_id device = (*devices)->devices[i]; cl_ulong device_output; HGPU_GPU_error_message(clGetDeviceInfo(device,parameter,sizeof(device_output),&device_output,NULL),"clGetDeviceInfo failed"); if (device_output>=min_value) desired_devices++; } HGPU_GPU_devices* result; if(desired_devices){ result = HGPU_GPU_devices_new(desired_devices); int device_index=0; for(unsigned int i=0; i<number_of_devices; i++){ cl_device_id device = (*devices)->devices[i]; cl_ulong device_output; HGPU_GPU_error_message(clGetDeviceInfo(device,parameter,sizeof(device_output),&device_output,NULL),"clGetDeviceInfo failed"); if (device_output>=min_value) result->devices[device_index++] = device; } } else result = HGPU_GPU_devices_new_empty(); HGPU_GPU_devices_delete(devices); (*devices) = result; }
// select OpenCL devices by device available void HGPU_GPU_devices_select_by_device_and_compiler_available(HGPU_GPU_devices** devices){ unsigned int number_of_devices = HGPU_GPU_devices_get_number(*devices); if (!number_of_devices) HGPU_GPU_error(HGPU_ERROR_NO_DEVICE); cl_uint desired_devices = 0; for(unsigned int i=0; i<number_of_devices; i++){ cl_device_id device = (*devices)->devices[i]; cl_bool device_available; cl_bool compiler_available; HGPU_GPU_error_message(clGetDeviceInfo(device,CL_DEVICE_AVAILABLE,sizeof(device_available),&device_available,NULL),"clGetDeviceInfo failed"); HGPU_GPU_error_message(clGetDeviceInfo(device,CL_DEVICE_COMPILER_AVAILABLE,sizeof(device_available),&compiler_available,NULL),"clGetDeviceInfo failed"); if (device_available & compiler_available) desired_devices++; } HGPU_GPU_devices* result; if(desired_devices){ result = HGPU_GPU_devices_new(desired_devices); int device_index=0; for(unsigned int i=0; i<number_of_devices; i++){ cl_device_id device = (*devices)->devices[i]; cl_bool device_available; cl_bool compiler_available; HGPU_GPU_error_message(clGetDeviceInfo(device,CL_DEVICE_AVAILABLE,sizeof(device_available),&device_available,NULL),"clGetDeviceInfo failed"); HGPU_GPU_error_message(clGetDeviceInfo(device,CL_DEVICE_COMPILER_AVAILABLE,sizeof(device_available),&compiler_available,NULL),"clGetDeviceInfo failed"); if (device_available & compiler_available) result->devices[device_index++] = device; } } else result = HGPU_GPU_devices_new_empty(); HGPU_GPU_devices_delete(devices); (*devices) = result; }
// select OpenCL devices by type void HGPU_GPU_devices_select_by_type(HGPU_GPU_devices** devices,cl_device_type device_type){ unsigned int number_of_devices = HGPU_GPU_devices_get_number(*devices); if (!number_of_devices) HGPU_GPU_error(HGPU_ERROR_NO_DEVICE); cl_uint desired_devices = 0; for(unsigned int i=0; i<number_of_devices; i++){ cl_device_id device = (*devices)->devices[i]; cl_device_type dev_type; HGPU_GPU_error_message(clGetDeviceInfo(device,CL_DEVICE_TYPE,sizeof(dev_type),&dev_type,NULL),"clGetDeviceInfo failed"); if (dev_type & device_type) desired_devices++; } HGPU_GPU_devices* result; if(desired_devices){ result = HGPU_GPU_devices_new(desired_devices); int device_index=0; for(unsigned int i=0; i<number_of_devices; i++){ cl_device_id device = (*devices)->devices[i]; cl_device_type dev_type; HGPU_GPU_error_message(clGetDeviceInfo(device,CL_DEVICE_TYPE,sizeof(dev_type),&dev_type,NULL),"clGetDeviceInfo failed"); if (dev_type & device_type) result->devices[device_index++] = device; } } else result = HGPU_GPU_devices_new_empty(); HGPU_GPU_devices_delete(devices); (*devices) = result; }
// select OpenCL devices by vendor void HGPU_GPU_devices_select_by_vendor(HGPU_GPU_devices** devices,HGPU_GPU_vendor vendor){ unsigned int number_of_devices = HGPU_GPU_devices_get_number(*devices); if (!number_of_devices) HGPU_GPU_error(HGPU_ERROR_NO_DEVICE); char infobuf[HGPU_MAX_STR_INFO_LENGHT]; cl_uint desired_devices = 0; for(unsigned int i=0; i<number_of_devices; i++){ cl_device_id GPU_device = (*devices)->devices[i]; HGPU_GPU_error_message(clGetDeviceInfo(GPU_device,CL_DEVICE_VENDOR,sizeof(infobuf),infobuf,NULL),"clGetDeviceInfo failed"); if ((HGPU_convert_vendor_from_str(infobuf)==vendor) || (vendor==HGPU_GPU_vendor_any)) desired_devices++; } HGPU_GPU_devices* result; if(desired_devices){ result = HGPU_GPU_devices_new(desired_devices); int j=0; for(unsigned int i=0; i<number_of_devices; i++){ cl_device_id GPU_device = (*devices)->devices[i]; HGPU_GPU_error_message(clGetDeviceInfo(GPU_device,CL_DEVICE_VENDOR,sizeof(infobuf),infobuf,NULL),"clGetDeviceInfo failed"); if ((HGPU_convert_vendor_from_str(infobuf)==vendor) || (vendor==HGPU_GPU_vendor_any)) result->devices[j++] = GPU_device; } } else result = HGPU_GPU_devices_new_empty(); HGPU_GPU_devices_delete(devices); (*devices) = result; }
// get OpenCL device info char* HGPU_GPU_device_get_info_str(cl_device_id device,cl_device_info parameter){ size_t parameter_length; HGPU_GPU_error_message(clGetDeviceInfo(device,parameter,0,NULL,¶meter_length),"clGetDeviceInfo failed"); char* result_str = (char*) calloc(parameter_length,sizeof(char)); HGPU_GPU_error_message(clGetDeviceInfo(device,parameter,(parameter_length),result_str,NULL),"clGetDeviceInfo failed"); return result_str; }
// get OpenCL platform info char* HGPU_GPU_platform_get_info_str(cl_platform_id platform,cl_platform_info parameter){ size_t parameter_length; HGPU_GPU_error_message(clGetPlatformInfo(platform,parameter,0,NULL,¶meter_length),"clGetPlatformInfo failed"); char* result_str = (char*) calloc(parameter_length,sizeof(char)); HGPU_GPU_error_message(clGetPlatformInfo(platform,parameter,(parameter_length),result_str,NULL),"clGetPlatformInfo failed"); return result_str; }
// get all OpenCL devices HGPU_GPU_devices* HGPU_GPU_devices_get_on_platform(cl_platform_id platform){ cl_uint number_of_devices = HGPU_GPU_devices_get_number_on_platform(platform); HGPU_GPU_devices* result = HGPU_GPU_devices_new(number_of_devices); HGPU_GPU_error_message(clGetDeviceIDs(platform,CL_DEVICE_TYPE_ALL,number_of_devices, result->devices, &result->number_of_devices),"clGetDeviceIDs failed"); if(!result->number_of_devices) HGPU_GPU_error_message(HGPU_ERROR_NO_PLATFORM,"there are no any available OpenCL devices"); return result; }
// new OpenCL platforms HGPU_GPU_platforms* HGPU_GPU_platforms_new(unsigned int number_of_platforms){ if (!number_of_platforms) HGPU_GPU_error_message(HGPU_ERROR_NO_PLATFORM,NULL); if (number_of_platforms>HGPU_GPU_MAX_PLATFORMS) HGPU_GPU_error_message(HGPU_ERROR_NO_MEMORY,"exceed maximal number of descriptions for platforms"); HGPU_GPU_platforms* result = (HGPU_GPU_platforms*) calloc(1,sizeof(HGPU_GPU_platforms)); result->platforms = (cl_platform_id*) calloc(number_of_platforms,sizeof(cl_platform_id)); result->number_of_platforms = number_of_platforms; return result; }
// get vendor of OpenCL platform HGPU_GPU_vendor HGPU_GPU_platform_get_vendor(cl_platform_id platform){ size_t parameter_length; HGPU_GPU_error_message(clGetPlatformInfo(platform,CL_PLATFORM_VENDOR,0,NULL,¶meter_length),"clGetPlatformInfo failed"); char* result_str = (char*) calloc(parameter_length+1,sizeof(char)); HGPU_GPU_error_message(clGetPlatformInfo(platform,CL_PLATFORM_VENDOR,(parameter_length+1),result_str,NULL),"clGetPlatformInfo failed"); HGPU_GPU_vendor vendor = HGPU_convert_vendor_from_str(result_str); free(result_str); return vendor; }
// get vendor of OpenCL device HGPU_GPU_vendor HGPU_GPU_device_get_vendor(cl_device_id device){ size_t parameter_length; HGPU_GPU_error_message(clGetDeviceInfo(device,CL_DEVICE_VENDOR,0,NULL,¶meter_length),"clGetDeviceInfo failed"); char* result_str = (char*) calloc(parameter_length+1,sizeof(char)); HGPU_GPU_error_message(clGetDeviceInfo(device,CL_DEVICE_VENDOR,(parameter_length+1),result_str,NULL),"clGetDeviceInfo failed"); HGPU_GPU_vendor vendor = HGPU_convert_vendor_from_str(result_str); free(result_str); return vendor; }
// get all OpenCL platforms HGPU_GPU_platforms* HGPU_GPU_platforms_get(void){ cl_uint GPU_platforms_number = 0; HGPU_GPU_error_message(clGetPlatformIDs(0,NULL,&GPU_platforms_number),"clGetPlatformIDs failed"); if(!GPU_platforms_number) HGPU_GPU_error_message(HGPU_ERROR_NO_PLATFORM,"there are no any available OpenCL platforms"); HGPU_GPU_platforms* result = HGPU_GPU_platforms_new(GPU_platforms_number); HGPU_GPU_error_message(clGetPlatformIDs(GPU_platforms_number,result->platforms,&result->number_of_platforms),"clGetPlatformIDs failed"); if(!result->number_of_platforms) HGPU_GPU_error_message(HGPU_ERROR_NO_PLATFORM,"there are no any available OpenCL platforms"); return result; }
// profile buffer unmap void HGPU_GPU_buffer_profile_unmap(HGPU_GPU_buffer* buffer){ if ((buffer) && (buffer->buffer_write_event)) { cl_ulong buffer_write_start = 0; cl_ulong buffer_write_finish = 0; HGPU_GPU_error_message(clGetEventProfilingInfo(buffer->buffer_write_event, CL_PROFILING_COMMAND_END, sizeof(cl_ulong), &buffer_write_finish, 0),"clGetEventProfilingInfo failed"); HGPU_GPU_error_message(clGetEventProfilingInfo(buffer->buffer_write_event, CL_PROFILING_COMMAND_START, sizeof(cl_ulong), &buffer_write_start, 0),"clGetEventProfilingInfo failed"); buffer->buffer_write_elapsed_time += (double) (buffer_write_finish-buffer_write_start); buffer->buffer_write_start = buffer_write_start; buffer->buffer_write_finish = buffer_write_finish; } }
// get next available device cl_device_id HGPU_GPU_device_get_next(HGPU_GPU_devices* devices,cl_device_id device){ unsigned int number_of_devices = HGPU_GPU_devices_get_number(devices); if (!number_of_devices) HGPU_GPU_error_message(HGPU_ERROR_NO_DEVICE,"there is no any desired OpenCL device"); unsigned int device_last_index = number_of_devices; for (unsigned int i=0;i<number_of_devices;i++){ if (devices->devices[i]==device){ device_last_index = i; i = number_of_devices; } } if (device_last_index>=(number_of_devices-1)) HGPU_GPU_error_message(HGPU_ERROR_NO_DEVICE,"there is no any desired OpenCL device"); return devices->devices[device_last_index+1]; }
// get number of OpenCL devices unsigned int HGPU_GPU_devices_get_number_on_platform(cl_platform_id platform){ cl_uint number_of_devices = 0; cl_int get_number_of_devices_result = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 0, NULL, &number_of_devices); if (get_number_of_devices_result!=CL_DEVICE_NOT_FOUND) HGPU_GPU_error_message(get_number_of_devices_result, "clGetDeviceIDs failed"); return number_of_devices; }
// get best available device cl_device_id HGPU_GPU_device_get_best(HGPU_GPU_devices* devices){ if ((!devices) || (!HGPU_GPU_devices_get_number(devices))) HGPU_GPU_error_message(HGPU_ERROR_NO_DEVICE,"there is no any desired OpenCL device"); HGPU_GPU_devices* devs = HGPU_GPU_devices_clone(devices); HGPU_GPU_devices_sort(&devs); cl_device_id result = devs->devices[0]; return result; }
// new OpenCL devices HGPU_GPU_devices* HGPU_GPU_devices_new(unsigned int number_of_devices){ if (!number_of_devices) HGPU_GPU_error(HGPU_ERROR_NO_DEVICE); if (number_of_devices>HGPU_GPU_MAX_DEVICES) HGPU_GPU_error_message(HGPU_ERROR_NO_MEMORY,"exceed maximal number of descriptions for devices"); HGPU_GPU_devices* result = (HGPU_GPU_devices*) calloc(1,sizeof(HGPU_GPU_devices)); result->devices = (cl_device_id*) calloc(number_of_devices,sizeof(cl_device_id)); result->number_of_devices = number_of_devices; return result; }
// create buffer cl_mem HGPU_GPU_buffer_create(cl_context context,cl_mem_flags flags,size_t buffer_size_in_bytes,void* host_ptr_to_buffer){ cl_mem result = NULL; if (!context) return result; cl_int GPU_error = CL_SUCCESS; result = clCreateBuffer(context,flags,buffer_size_in_bytes,host_ptr_to_buffer,&GPU_error); HGPU_GPU_error_message(GPU_error,"clCreateBuffer failed"); return result; }
// check if OpenCL supports double precision bool HGPU_GPU_device_check_double_precision(cl_device_id device){ bool result = false; char device_output[HGPU_MAX_STR_INFO_LENGHT]; HGPU_GPU_error_message(clGetDeviceInfo(device,CL_DEVICE_EXTENSIONS,HGPU_MAX_STR_INFO_LENGHT,&device_output,NULL),"clGetDeviceInfo failed"); HGPU_string_to_lowercase(device_output); if (strstr(device_output,"cl_khr_fp64")) result = true; return result; }
// get OpenCL device by index cl_device_id HGPU_GPU_device_get_by_index_on_platform(cl_platform_id platform,unsigned int device_index){ cl_device_id result; HGPU_GPU_devices* devices = HGPU_GPU_devices_get_on_platform(platform); if (HGPU_GPU_devices_get_number(devices)<=device_index) { HGPU_GPU_devices_delete(&devices); HGPU_GPU_error_message(HGPU_ERROR_NO_DEVICE,"there is no any desired OpenCL device"); } result = devices->devices[device_index]; HGPU_GPU_devices_delete(&devices); return result; }
// get OpenCL platforms by index cl_platform_id HGPU_GPU_platform_get_by_index(unsigned int platform_index){ cl_platform_id result; HGPU_GPU_platforms* platforms = HGPU_GPU_platforms_get(); if (HGPU_GPU_platforms_get_number(platforms)<=platform_index) { HGPU_GPU_platforms_delete(&platforms); HGPU_GPU_error_message(HGPU_ERROR_NO_PLATFORM,"there is no any desired OpenCL platform"); } result = platforms->platforms[platform_index]; HGPU_GPU_platforms_delete(&platforms); return result; }
// buffer unmap (asynchronous) void HGPU_GPU_buffer_unmap_async(HGPU_GPU_buffer* buffer,cl_command_queue queue,void* data_ptr){ if (!buffer){ HGPU_GPU_error_note(HGPU_ERROR_BAD_BUFFER,"Trying to use null-buffer!"); return; } cl_event buffer_event = NULL; HGPU_GPU_error_message(clEnqueueUnmapMemObject(queue,buffer->buffer,data_ptr,0,NULL,&buffer_event),"clEnqueueUnmapMemObject failed"); buffer->buffer_write_event = buffer_event; buffer->buffer_write_number_of++; }
// get index of OpenCL device by device unsigned int HGPU_GPU_device_get_index_of(cl_device_id device){ unsigned int result = 0; HGPU_GPU_devices* devices = HGPU_GPU_devices_get(); bool flag = true; while ((result<HGPU_GPU_devices_get_number(devices))&&(flag)){ if (devices->devices[result]==device) flag = false; else result++; } HGPU_GPU_devices_delete(&devices); if (flag) HGPU_GPU_error_message(HGPU_ERROR_NO_DEVICE,"there is no any desired OpenCL device"); return result; }
// get index of OpenCL platform by platform unsigned int HGPU_GPU_platform_get_index_of(cl_platform_id platform){ unsigned int result = 0; HGPU_GPU_platforms* platforms = HGPU_GPU_platforms_get(); bool flag = true; while ((result<HGPU_GPU_platforms_get_number(platforms))&&(flag)){ if (platforms->platforms[result]==platform) flag = false; else result++; } HGPU_GPU_platforms_delete(&platforms); if (flag) HGPU_GPU_error_message(HGPU_ERROR_NO_PLATFORM,"there is no any desired OpenCL platform"); return result; }
// select OpenCL platforms by vendor void HGPU_GPU_platforms_select_by_vendor(HGPU_GPU_platforms** platforms,HGPU_GPU_vendor vendor){ unsigned int platforms_number = HGPU_GPU_platforms_get_number(*platforms); if (!platforms_number) HGPU_GPU_error(HGPU_ERROR_NO_PLATFORM); char infobuf[HGPU_GPU_MAX_STR_INFO_LENGHT]; cl_uint desired_platforms = 0; for(unsigned int i=0; i<platforms_number; i++){ cl_platform_id GPU_platform = (*platforms)->platforms[i]; HGPU_GPU_error_message(clGetPlatformInfo(GPU_platform,CL_PLATFORM_VENDOR,sizeof(infobuf),infobuf,NULL),"clGetPlatformInfo failed"); if ((HGPU_convert_vendor_from_str(infobuf)==vendor) || (vendor==HGPU_GPU_vendor_any)) desired_platforms++; } if(!desired_platforms) HGPU_GPU_error(HGPU_ERROR_NO_PLATFORM); HGPU_GPU_platforms* result = HGPU_GPU_platforms_new(desired_platforms); int j=0; for(unsigned int i=0; i<platforms_number; i++){ cl_platform_id GPU_platform = (*platforms)->platforms[i]; HGPU_GPU_error_message(clGetPlatformInfo(GPU_platform,CL_PLATFORM_VENDOR,sizeof(infobuf),infobuf,NULL),"clGetPlatformInfo failed"); if ((HGPU_convert_vendor_from_str(infobuf)==vendor) || (vendor==HGPU_GPU_vendor_any)) result->platforms[j++] = GPU_platform; } HGPU_GPU_platforms_delete(platforms); (*platforms) = result; }
// get version from string HGPU_GPU_version HGPU_GPU_version_get(char* version_str){ HGPU_GPU_version version; version.major = 0; version.minor = 0; if (strlen(version_str)< 10) HGPU_GPU_error_message(HGPU_ERROR_BAD_OPENCL_VERSION,"bad OpenCL version"); char* temp = HGPU_string_clone(version_str); HGPU_string_delete_symbols_except_numbers_and_dots(temp); HGPU_string_trim(temp); sscanf_s(temp,"%d.%d",&version.major,&version.minor); free(temp); return version; }
// get rating of OpenCL device unsigned int HGPU_GPU_device_get_rating(cl_device_id device){ //+++ GPU - 1000 points //+++ Double precision - 100 points //+++ OpenCL major version - 10 points //+++ OpenCL minor version - 1 point unsigned int result = 0; if (device){ cl_device_type device_type; HGPU_GPU_error_message(clGetDeviceInfo(device,CL_DEVICE_TYPE,sizeof(device_type),&device_type,NULL),"clGetDeviceInfo failed"); if (device_type==CL_DEVICE_TYPE_GPU) result += 1000; if (HGPU_GPU_device_check_double_precision(device)) result += 100; HGPU_GPU_version version = HGPU_GPU_device_get_version(device); result += version.major * 10; result += version.minor; } return result; }
// buffer map (asynchronous) void* HGPU_GPU_buffer_map_async(HGPU_GPU_buffer* buffer,cl_command_queue queue){ void* result = NULL; if (!buffer){ HGPU_GPU_error_note(HGPU_ERROR_BAD_BUFFER,"Trying to use null-buffer!"); return result; } cl_int GPU_error = 0; cl_event buffer_event = NULL; size_t size = buffer->size*buffer->sizeof_element; result = clEnqueueMapBuffer(queue,buffer->buffer,CL_TRUE,CL_MAP_READ|CL_MAP_WRITE,0,size,0,NULL,&buffer_event,&GPU_error); HGPU_GPU_error_message(GPU_error,"clEnqueueMapBuffer failed"); buffer->buffer_read_event = buffer_event; buffer->buffer_read_number_of++; buffer->mapped_ptr = (unsigned int*) result; return result; }
// buffer release void HGPU_GPU_buffer_mem_release(cl_mem buffer){ cl_int GPU_error = clReleaseMemObject(buffer); HGPU_GPU_error_message(GPU_error,"clReleaseMemObject failed"); }
// wait for event void HGPU_GPU_buffer_wait_for_event(cl_event* buffer_event){ if (buffer_event) { HGPU_GPU_error_message(clWaitForEvents(1, buffer_event),"clWaitForEvents failed"); } }
// get first available platform cl_platform_id HGPU_GPU_platform_get_first(HGPU_GPU_platforms* platforms){ if (!HGPU_GPU_platforms_get_number(platforms)) HGPU_GPU_error_message(HGPU_ERROR_NO_PLATFORM,"there is no any desired OpenCL platform"); return platforms->platforms[0]; }