20 Mar 2010
One might think that SDKs are supposed to facilitate programming, which
not the case for the NVidia OpenCL SDK. Here is how I got very
basic OpenCL code working...
Disclaimer: Linux only, using Ubuntu 8.10 Hardy
First, it is not clear what version of the graphics driver, CUDA and OpenCL SDK you are supposed to install. The latest (stable) graphics drivers do not include OpenCL.so, version 195.36.15 worked for me.
Second, what version of CUDA? cudatoolkit 3.0 worked for me, maybe you are supposed to use cudasdk 2.3? or maybe cudatoolkit 2.3?
Third, what version of OpenCL? the package is convincingly named gpucomputingsdk 2.3a, so maybe to be used with the 2.3 CUDA stuff? CUDA SDK 3.x also contains the relevant OpenCL header files, and there are no libs except for the OpenCL.so shipped with the graphics driver; good documentation is available from the khronos size.
In the end, the OpenCL samples fail to work as
// Create the OpenCL context on a GPU device cxGPUContext = clCreateContextFromType(0, CL_DEVICE_TYPE_GPU, NULL, NULL, &ciErr1);returns
-32 (CL_INVALID_PLATFORM)
, other samples just
crash. Turns out
that the first parameter must not be zero; specification says the
behaviour is implementation-defined if zero -- great idea to put such
code in the SDK samples. Properly calling
clGetPlatformIDs()
and you are good to go!
Here is some device query code which works for me:
#include "CL/cl.h" int main() { cl_uint n; cl_platform_id plat_ids[3]; cl_int ret = clGetPlatformIDs(3, plat_ids, &n); printf("ret = %d, platforms = %d\n", ret, n); for (cl_uint i = 0; i < n; i++) { char buf[1024]; size_t bytes; ret = clGetPlatformInfo(plat_ids[i], CL_PLATFORM_VERSION, sizeof(buf), buf, &bytes); printf("ret = %d, bytes = %d, version %s\n", ret, bytes, buf); ret = clGetPlatformInfo(plat_ids[i], CL_PLATFORM_NAME, sizeof(buf), buf, &bytes); printf("ret = %d, bytes = %d, name %s\n", ret, bytes, buf); } cl_device_id dev_ids[3]; ret = clGetDeviceIDs(plat_ids[0], CL_DEVICE_TYPE_GPU, 3, dev_ids, &n); printf("ret = %d, devices = %d\n", ret, n); char buf[1024]; size_t bytes; ret = clGetDeviceInfo(dev_ids[0], CL_DEVICE_AVAILABLE, sizeof(buf), buf, &bytes); printf("ret = %d, bytes = %d, avail %d\n", ret, bytes, *(cl_bool*) &buf); ret = clGetDeviceInfo(dev_ids[0], CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(buf), buf, &bytes); printf("ret = %d, bytes = %d, global mem %lld\n", ret, bytes, *(cl_ulong*) &buf); ret = clGetDeviceInfo(dev_ids[0], CL_DEVICE_LOCAL_MEM_SIZE, sizeof(buf), buf, &bytes); printf("ret = %d, bytes = %d, local mem %lld\n", ret, bytes, *(cl_ulong*) &buf); ret = clGetDeviceInfo(dev_ids[0], CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, sizeof(buf), buf, &bytes); printf("ret = %d, bytes = %d, global mem cache %lld\n", ret, bytes, *(cl_ulong*) &buf); ret = clGetDeviceInfo(dev_ids[0], CL_DEVICE_IMAGE_SUPPORT, sizeof(buf), buf, &bytes); printf("ret = %d, bytes = %d, image support %d\n", ret, bytes, *(cl_bool*) &buf); ret = clGetDeviceInfo(dev_ids[0], CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof(buf), buf, &bytes); printf("ret = %d, bytes = %d, image 2d max height %d\n", ret, bytes, *(size_t*) &buf); ret = clGetDeviceInfo(dev_ids[0], CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(buf), buf, &bytes); printf("ret = %d, bytes = %d, clock freq %d\n", ret, bytes, *(cl_uint*) &buf); ret = clGetDeviceInfo(dev_ids[0], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(buf), buf, &bytes); printf("ret = %d, bytes = %d, compute units %d\n", ret, bytes, *(cl_uint*) &buf); ret = clGetDeviceInfo(dev_ids[0], CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(buf), buf, &bytes); printf("ret = %d, bytes = %d, work group size %d\n", ret, bytes, *(size_t*) &buf); ret = clGetDeviceInfo(dev_ids[0], CL_DEVICE_NAME, sizeof(buf), buf, &bytes); printf("ret = %d, bytes = %d, name %s\n", ret, bytes, buf); cl_context_properties props[3]; props[0] = CL_CONTEXT_PLATFORM; props[1] = (cl_context_properties)plat_ids[0]; props[2] = 0; cl_context ctx = clCreateContextFromType(props, CL_DEVICE_TYPE_GPU, 0, 0, &ret); printf("ret = %d\n", ret); return 0; }
posted at: 12:30 | path: /rant | permanent link