/* * General note: Error checking is kind of a circus in this file */ #include #include #include #include "scolor.h" cl_device_info query_items[] = {CL_DEVICE_TYPE, CL_DEVICE_VENDOR_ID, CL_DEVICE_MAX_COMPUTE_UNITS, CL_DEVICE_GLOBAL_MEM_SIZE, CL_DEVICE_LOCAL_MEM_SIZE, CL_DEVICE_NAME, CL_DRIVER_VERSION, CL_DEVICE_VENDOR, CL_DEVICE_EXTENSIONS}; char* query_names[] = {"CL_DEVICE_TYPE", "CL_DEVICE_VENDOR_ID", "CL_DEVICE_MAX_COMPUTE_UNITS", "CL_DEVICE_GLOBAL_MEM_SIZE", "CL_DEVICE_LOCAL_MEM_SIZE", "CL_DEVICE_NAME", "CL_DRIVER_VERSION", "CL_DEVICE_VENDOR", "CL_DEVICE_EXTENSIONS"}; #define check(m) if(errcode != CL_SUCCESS){ puts(m); goto err; } int main(){ cl_platform_id plt_ids[10]; cl_uint plt_count; cl_device_id dev_ids[10]; cl_uint dev_count; char pname[1024]; cl_int retval = clGetPlatformIDs(10, plt_ids, &plt_count); if(retval != CL_SUCCESS){ printf(RED("clGetPlatformIDs failed with error %d\n"), retval); goto err; } for(int i = 0; i < plt_count; i++){ printf(PURPLE("Platform %d (ID %lu):\n"), i, (size_t)plt_ids[i]); cl_int retval = clGetDeviceIDs(plt_ids[i], CL_DEVICE_TYPE_ALL, 10, dev_ids, &dev_count); if(retval != CL_SUCCESS){ printf(RED("clGetPlatformIDs failed with error %d\n"), retval); goto err; } for(int j = 0; j < dev_count; j++){ printf(GREEN("Device %d (ID %lu):\n"), j, (size_t)dev_ids[j]); for(int q = 0; q < sizeof(query_items)/sizeof(cl_device_info); q++){ size_t psize; retval = clGetDeviceInfo(dev_ids[j], query_items[q], 1024, pname, &psize); if(retval != CL_SUCCESS){ printf(RED("Query Failed: %s\n"), query_names[q]); continue; } if(isalnum(pname[0]) || (psize != 4 && psize != 8)){ // Not bulletproof pname[psize] = 0; printf("%s : "BBLUE("%s")" (%ld)\n", query_names[q], pname, psize); } else if(psize == 4) { printf("%s : "BBLUE("%u")" (%ld)\n", query_names[q], *((cl_uint*)pname), psize); } else { printf("%s : "BBLUE("%lu")" (%ld)\n", query_names[q], *((size_t*)pname), psize); } } } } /* We'll assume platform 0, device 0 from this point on */ cl_int errcode; cl_context context = clCreateContext(0, 1, dev_ids, 0, 0, &errcode); if(errcode != CL_SUCCESS) goto err; /* Note here: You won't find a manpage for clCreateCommandQueueWithProperties on Debian Linux, and probably others * The deprecated version is just called clCreateCommandQueue, and they take the same parameters. * On Debian at least, the compiler will warn that clCreateCommandQueue is deprecated, and accept this version * nVidia has been slow with OpenCL support and clCreateCommandQueueWithProperties is OpenCL 2.0+, but it works */ cl_command_queue queue = clCreateCommandQueueWithProperties(context, dev_ids[0], 0, &errcode); check("clCreateCommandQueue"); int input[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; cl_mem input_buffer = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(input), input, &errcode); if(errcode != CL_SUCCESS) goto err; cl_mem output_buffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY, sizeof(input), 0, &errcode); if(errcode != CL_SUCCESS) goto err; const char* kernel_code = " \ __kernel void squares(__global int* in, __global int* out){ \ const int i = get_global_id(0); \ out[i] = in[i] * in[i]; \ }"; cl_program program = clCreateProgramWithSource(context, 1, &kernel_code, 0, &errcode); check("clCreateProgramWithSource"); if(clBuildProgram(program, 1, dev_ids, 0, 0, 0) != CL_SUCCESS){ puts("clBuildProgram"); goto err; } cl_kernel kernel = clCreateKernel(program, "squares", &errcode); check("clCreateKernel"); errcode = clSetKernelArg(kernel, 0, sizeof(cl_mem), &input_buffer); check("clSetKernelArg"); if(CL_SUCCESS != (errcode = clSetKernelArg(kernel, 1, sizeof(cl_mem), &output_buffer))){ printf("clSetKernelArg #2\n"); goto err; } const size_t worklen = sizeof(input) / sizeof(float); if(CL_SUCCESS != (errcode = clEnqueueNDRangeKernel(queue, kernel, 1, 0, &worklen, 0, 0, 0, 0))){ perror("clEnqueueNDRangeKernel"); goto err; } errcode = clEnqueueReadBuffer(queue, output_buffer, CL_TRUE, 0, sizeof(input), input, 0, 0, 0); check("clEnqueueReadBuffer"); printf(BGREEN("Results: ")PURPLE("[")); for(int i = 0; i < sizeof(input) / sizeof(float); i++){ printf(PURPLE("%d, "), input[i]); } printf(PURPLE("\b\b]\n")); return 0; err: printf(RED("We have failed to discover the wonders of OpenCL, errcode = %d\n"), errcode); return 1; }