diff --git a/checkin_notes b/checkin_notes index 4ead4a2069..4edb24fffe 100644 --- a/checkin_notes +++ b/checkin_notes @@ -5345,3 +5345,11 @@ Charlie 31 Aug 2011 lib/ coproc.cpp, .h gui_rpc_client_ops.cpp + +Charlie 31 Aug 2011 + - lib: Add OPENCL_REFERENCE boinc_getopencl_ids(int argc, char** argv) + to be called by OpenCL project applications to get the platform ID + and device ID of the GPU assigned to the task by the scheduler. + + lib/ + coproc.cpp, .h diff --git a/lib/coproc.cpp b/lib/coproc.cpp index 8ca3929cf9..3bcc3a369d 100644 --- a/lib/coproc.cpp +++ b/lib/coproc.cpp @@ -29,14 +29,26 @@ #include #endif + #ifdef _WIN32 #include "win_util.h" +#else +#ifdef __APPLE__ +// Suppress obsolete warning when building for OS 10.3.9 +#define DLOPEN_NO_WARN +#include +#endif +#include "config.h" +#include +#include +#include #endif #include "error_numbers.h" #include "filesys.h" #include "parse.h" #include "util.h" +#include "str_replace.h" #include "coproc.h" @@ -657,3 +669,175 @@ void COPROC_ATI::description(char* buf) { name, version, attribs.localRAM/1024.*1024., peak_flops/1.e9 ); } + +#ifndef __WXWINDOWS__ /* Exclude from Manager */ + +#ifdef _WIN32 +static HMODULE opencl_lib = NULL; + +typedef cl_int (__stdcall *CL_PLATFORMIDS) (cl_uint, cl_platform_id*, cl_uint*); +typedef cl_int (__stdcall *CL_DEVICEIDS)(cl_platform_id, cl_device_type, cl_uint, cl_device_id*, cl_uint*); +typedef cl_int (__stdcall *CL_INFO) (cl_device_id, cl_device_info, size_t, void*, size_t*); + +static CL_PLATFORMIDS __clGetPlatformIDs = NULL; +static CL_DEVICEIDS __clGetDeviceIDs = NULL; +static CL_INFO __clGetDeviceInfo = NULL; + +#else + +static jmp_buf resume; + +static void segv_handler(int) { + longjmp(resume, 1); +} + +static void* opencl_lib = NULL; + +static cl_int (*__clGetPlatformIDs)(cl_uint /* num_entries */, + cl_platform_id * /* platforms */, + cl_uint * /* num_platforms */); +static cl_int (*__clGetDeviceIDs)(cl_platform_id /* platform */, + cl_device_type /* device_type */, + cl_uint /* num_entries */, + cl_device_id * /* devices */, + cl_uint * /* num_devices */); +static cl_int (*__clGetDeviceInfo)(cl_device_id /* device */, + cl_device_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */); +#endif + +void boinc_getopencl_ids(char *type, int device_num, OPENCL_REFERENCE *ref) { + cl_int errnum; + cl_platform_id platforms[MAX_OPENCL_PLATFORMS]; + cl_uint num_platforms, platform_index, num_devices; + cl_device_id devices[MAX_COPROC_INSTANCES]; + char vendor[256]; // Device vendor (NVIDIA, ATI, AMD, etc.) + +#ifdef _WIN32 + opencl_lib = LoadLibrary("OpenCL.dll"); + if (!opencl_lib) { + ref->retval = ERR_NOT_IMPLEMENTED; + return; + } + __clGetPlatformIDs = (CL_PLATFORMIDS)GetProcAddress( opencl_lib, "clGetPlatformIDs" ); + __clGetDeviceIDs = (CL_DEVICEIDS)GetProcAddress( opencl_lib, "clGetDeviceIDs" ); + __clGetDeviceInfo = (CL_INFO)GetProcAddress( opencl_lib, "clGetDeviceInfo" ); +#else +#ifdef __APPLE__ + opencl_lib = dlopen("/System/Library/Frameworks/OpenCL.framework/Versions/Current/OpenCL", RTLD_NOW); +#else +//TODO: Is this correct? + opencl_lib = dlopen("libOpenCL.so", RTLD_NOW); +#endif + + if (!opencl_lib) { + ref->retval = ERR_NOT_IMPLEMENTED; + return; + } + + __clGetPlatformIDs = (cl_int(*)(cl_uint, cl_platform_id*, cl_uint*)) dlsym( opencl_lib, "clGetPlatformIDs" ); + __clGetDeviceIDs = (cl_int(*)(cl_platform_id, cl_device_type, cl_uint, cl_device_id*, cl_uint*)) dlsym( opencl_lib, "clGetDeviceIDs" ); + __clGetDeviceInfo = (cl_int(*)(cl_device_id, cl_device_info, size_t, void*, size_t*)) dlsym( opencl_lib, "clGetDeviceInfo" ); +#endif + if ((!__clGetPlatformIDs) || (!__clGetDeviceIDs) || (!__clGetDeviceInfo)) { + ref->retval = ERR_NOT_IMPLEMENTED; + goto bail; + } + + errnum = (*__clGetPlatformIDs)(MAX_OPENCL_PLATFORMS, platforms, &num_platforms); + if (num_platforms == 0) errnum = CL_DEVICE_NOT_FOUND; + if (errnum != CL_SUCCESS) { + ref->retval = errnum; + goto bail; + } + + for (platform_index=0; platform_index (cl_uint)(device_num + 1)) continue; + + cl_device_id device_id = devices[device_num]; + + errnum = (*__clGetDeviceInfo)(device_id, CL_DEVICE_VENDOR, sizeof(vendor), vendor, NULL); + if ((errnum != CL_SUCCESS) || (vendor[0] == 0)) continue; + + if ((strstr(vendor, "AMD")) || + (strstr(vendor, "Advanced Micro Devices, Inc.")) + ) { + strcpy(vendor, GPU_TYPE_ATI); + } + + if (!strcmp(vendor, type)) { + ref->device_id = device_id; + ref->platform_id = platforms[platform_index]; + break; + } + } + +bail: +#ifndef _WIN32 + dlclose(opencl_lib); +#endif + + if ((ref->retval == CL_SUCCESS) && (ref->device_id == NULL)) { + ref->retval = CL_DEVICE_NOT_FOUND; + } +} + +OPENCL_REFERENCE boinc_getopencl_ids(int argc, char** argv) { + OPENCL_REFERENCE ref; + char type[256]; + int device_num; + + memset(&ref, 0, sizeof(struct OPENCL_REFERENCE)); + type[0] = '\0'; + device_num = -1; + + for (int i = 1; i < argc; i++) { + if (!strcmp(argv[i], "--gpu_type")) { + strlcpy(type, argv[++i], sizeof(type)); + } + if (!strcmp(argv[i], "--device")) { + device_num = atoi(argv[++i]); + } + } + + if (type[0] == '\0'){ + ref.retval = CL_INVALID_DEVICE_TYPE; + return ref; + } + + if (device_num < 0) { + ref.retval = CL_INVALID_DEVICE; + return ref; + } + +#ifdef _WIN32 + try { + boinc_getopencl_ids(type, device_num, &ref); + } + catch (...) { + ref.retval = ERR_SIGNAL_CATCH; + } +#else + void (*old_sig)(int) = signal(SIGSEGV, segv_handler); + if (setjmp(resume)) { + ref.retval = ERR_SIGNAL_CATCH; + } else { + boinc_getopencl_ids(type, device_num, &ref); + } + + signal(SIGSEGV, old_sig); +#endif + + if ((ref.retval == CL_SUCCESS) && (ref.device_id == NULL)) { + ref.retval = CL_DEVICE_NOT_FOUND; + } + + return ref; +} +#endif // __WXWINDOWS \ No newline at end of file diff --git a/lib/coproc.h b/lib/coproc.h index 78d030ae58..75a18a88f0 100644 --- a/lib/coproc.h +++ b/lib/coproc.h @@ -85,6 +85,12 @@ #define GPU_TYPE_ATI "ATI" #define GPU_TYPE_AMD GPU_TYPE_ATI +struct OPENCL_REFERENCE { + cl_device_id device_id; + cl_platform_id platform_id; + cl_int retval; +}; + // represents a requirement for a coproc. // This is a parsed version of the elements in an // (used in client only) @@ -405,4 +411,6 @@ struct COPROCS { } }; +OPENCL_REFERENCE boinc_getopencl_ids(int argc, char** argv); + #endif