91 get_device_id(
unsigned int platform_i,
unsigned int device_i);
117 run_example(
unsigned int nb_work_group,
unsigned int nb_work_items_by_work_group,
118 cl_device_id device_id,
bool debug,
const char* path);
128 const char sep =
'/';
129 const size_t size = strlen(path);
131 if ((size == 0) || (path[size - 1] == sep)) {
132 char* part = (
char*)malloc(
sizeof(
char) * (size + 1));
139 bool found_sep =
false;
144 if (path[j] == sep) {
151 char* part = (
char*)malloc(
sizeof(
char) * (j + 1));
154 strncpy(part, path, j + 1);
169 if (errors_map[i].code == code) {
170 return errors_map[i].
name;
180 const char*
const first_prefix =
"#line 1 \"";
181 const char*
const first_suffix =
"\"\n";
182 const size_t first_size = strlen(first_prefix) + strlen(filename) + strlen(first_suffix);
184 FILE*
const fin = fopen(filename,
"rb");
186 fseek(fin, 0l, SEEK_END);
188 const size_t file_size = ftell(fin);
189 const size_t size = first_size + file_size;
190 char*
const s = malloc(size + 1);
192 sprintf(s,
"%s%s%s", first_prefix, filename, first_suffix);
195 if (fread((
void*)(s + first_size), 1, size, fin) != file_size) {
196 fprintf(stderr,
"! Impossible to read file \"%s\"\n", filename);
212 cl_int error = clGetPlatformIDs(0, NULL, &nb);
215 if (platform_i >= nb) {
220 cl_platform_id* platform_ids;
222 platform_ids = (cl_platform_id*)malloc(
sizeof(cl_platform_id) * nb);
223 error = clGetPlatformIDs(nb, platform_ids, NULL);
227 const cl_platform_id platform_id = platform_ids[platform_i];
232 error = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_ALL, 0, NULL, &nb);
234 if (device_i >= nb) {
239 cl_device_id* device_ids;
241 device_ids = (cl_device_id*)malloc(
sizeof(cl_device_id) * nb);
242 error = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_ALL, nb, device_ids, NULL);
246 const cl_device_id device_id = device_ids[device_i];
260 cl_int error = clGetDeviceInfo(device_id, param_name, 0, NULL, &size);
265 result = (
char*)malloc(
sizeof(
char) * (size + 1));
266 error = clGetDeviceInfo(device_id, param_name, size, result, NULL);
276 if (message == NULL) {
277 fprintf(stderr,
"! OpenCL error %i %s\n", code,
error_name(code));
280 fprintf(stderr,
"! OpenCL error %i %s %s\n", code,
error_name(code), message);
288 run_example(
unsigned int nb_work_group,
unsigned int nb_work_items_by_work_group,
289 cl_device_id device_id,
bool debug,
const char* path) {
292 const size_t h_outs_byte_size =
sizeof(h_outs[0])*2;
294 uint64_t h_asserts[2] = {0, 0};
295 const size_t h_asserts_byte_size =
sizeof(h_asserts[0])*2;
297 float h_assert_float[1] = {0};
298 const size_t h_assert_float_byte_size =
sizeof(h_assert_float[0]);
300 assert(
sizeof(
float) == 4);
305 const cl_context context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &error);
311 const char*
const prefix =
"-I";
312 const char*
const suffix =
"../../OpenCL/";
313 const char*
const suffix_ndebug =
" -DNDEBUG";
314 const size_t options_max_size =
315 strlen(prefix) + strlen(path) + strlen(suffix) + strlen(suffix_ndebug);
316 char*
const options = malloc(
sizeof(
char) * (options_max_size + 1));
318 sprintf(options,
"%s%s%s", prefix, path, suffix);
321 fputs(
"OpenCL in DEBUG mode!\n", stderr);
325 strcat(options, suffix_ndebug);
328 const char*
const suffix_filename =
"../kernel/example.cl";
329 char*
const kernel_filename = malloc(
sizeof(
char)
330 * (options_max_size + strlen(suffix_filename) + 1));
332 sprintf(kernel_filename,
"%s%s", path, suffix_filename);
336 const cl_program program = clCreateProgramWithSource(context, 1, (
const char**)&kernel_src, NULL, &error);
341 error = clBuildProgram(program, 1, &device_id, options, NULL, NULL);
345 const cl_kernel kernel = clCreateKernel(program,
"example", &error);
351 #if __OPENCL_C_VERSION__ < 200 // CL_VERSION_2_0 352 cl_command_queue queue = clCreateCommandQueue(context, device_id, CL_QUEUE_PROFILING_ENABLE, &error);
354 const cl_queue_properties properties[] = {CL_QUEUE_PROPERTIES, CL_QUEUE_PROFILING_ENABLE, 0};
355 cl_command_queue queue = clCreateCommandQueueWithProperties(context, device_id, properties, &error);
362 cl_mem d_outs = clCreateBuffer(context, CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, h_outs_byte_size, h_outs, &error);
367 cl_mem d_assert_float;
370 d_asserts = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,
371 h_asserts_byte_size, h_asserts, &error);
374 d_assert_float = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,
375 h_assert_float_byte_size, h_assert_float, &error);
376 print_error(error,
"d_assert_float = clCreateBuffer");
381 const cl_uint n = 666;
383 error = clSetKernelArg(kernel, 0,
sizeof(n), &n);
386 error = clSetKernelArg(kernel, 1,
sizeof(d_outs), &d_outs);
390 const unsigned int nb_args = 2;
392 error = clSetKernelArg(kernel, nb_args,
sizeof(d_asserts), &d_asserts);
393 print_error(error,
"clSetKernelArg(..., d_asserts)");
395 error = clSetKernelArg(kernel, nb_args + 1,
sizeof(d_assert_float), &d_assert_float);
396 print_error(error,
"clSetKernelArg(..., d_assert_float)");
401 const size_t global_size = nb_work_items_by_work_group * nb_work_group;
402 const size_t local_size = nb_work_items_by_work_group;
404 puts(
"===== run kernel =====");
407 error = clEnqueueNDRangeKernel(queue,
422 puts(
"===== end kernel =====");
427 error = clEnqueueReadBuffer(queue, d_outs, CL_TRUE, 0,
428 h_outs_byte_size, h_outs, 0, NULL, NULL);
429 print_error(error,
"clEnqueueReadBuffer(..., d_outs, ...)");
432 error = clEnqueueReadBuffer(queue, d_asserts, CL_TRUE, 0,
433 h_asserts_byte_size, h_asserts, 0, NULL, NULL);
434 print_error(error,
"clEnqueueReadBuffer(..., d_asserts, ...)");
436 error = clEnqueueReadBuffer(queue, d_assert_float, CL_TRUE, 0,
437 h_assert_float_byte_size, h_assert_float, 0, NULL, NULL);
438 print_error(error,
"clEnqueueReadBuffer(..., d_assert_float, ...)");
440 const uint64_t line = h_asserts[0];
443 const uint64_t uint64_value = h_asserts[1];
444 const int64_t sint64_value = (int64_t)h_asserts[1];
445 const float float_value = h_assert_float[0];
447 fprintf(stderr,
"%s:%lu\tAssertion failed | Maybe\t%lu\t%li | Maybe\t%f\n",
448 kernel_filename, line, uint64_value, sint64_value, float_value);
457 printf(
"Results: (%u, %u)\n", h_outs[0], h_outs[1]);
459 free(kernel_filename);
463 clReleaseMemObject(d_outs);
465 clReleaseMemObject(d_asserts);
466 clReleaseMemObject(d_assert_float);
469 clReleaseCommandQueue(queue);
470 clReleaseProgram(program);
471 clReleaseKernel(kernel);
472 clReleaseContext(context);
486 main(
int argc,
const char*
const argv[]) {
493 signed int device_i = 0;
494 signed int platform_i = 0;
501 const char* arg = argv[i];
503 if ((strcmp(arg,
"--debug") == 0) || (strcmp(arg,
"--ndebug") == 0)) {
504 debug = (strcmp(arg,
"--debug") == 0);
506 else if (strcmp(arg,
"--device") == 0) {
512 const char* both_i = argv[i];
513 const size_t len = strlen(both_i);
514 bool only_platform =
true;
518 if (both_i[j] ==
':') {
519 only_platform =
false;
527 platform_i = atoi(both_i);
530 platform_i = atoi(both_i);
531 device_i = atoi(both_i + j + 1);
534 if ((platform_i < 0) || (device_i < 0)) {
544 const cl_device_id device_id =
get_device_id(platform_i, device_i);
550 printf(
"Device %u:%u %s\n", (
unsigned int)platform_i, (
unsigned int)device_i, device_name);
char * file_to_alloc_string(const char *filename)
Read the file and return its content to a (new allocated) string. If failed then print a error messag...
List of all error codes and names extracted from /usr/include/CL/cl.h.
char * get_device_info_alloc_string(cl_device_id device_id, cl_device_info param_name)
Return a (new allocated) string corresponding to device info parameter.
cl_device_id get_device_id(unsigned int platform_i, unsigned int device_i)
Return the given id device of the given platform OpenCL, or exit if doesn't exists.
const char * error_name(cl_int code)
Return the error name corresponding to the error code.
void print_error(cl_int code, const char *message)
If code != 0 then print an error message corresponding to the error code.
char * dirname_alloc(const char *path)
Return the directory part of path in a (new allocated) string.
int main(int argc, const char *const argv[])
Get the optional parameter –device platform:device and run the kernel ../kernel/example.cl.
const error_name_t errors_map[61]
List of all error codes and names extracted from /usr/include/CL/cl.h.
#define assert(test)
If test is true then do nothing. Else init (if they are still null) assert_result and assert_result_f...
void run_example(unsigned int nb_work_group, unsigned int nb_work_items_by_work_group, cl_device_id device_id, bool debug, const char *path)
Run the kernel ../kernel/example.cl.
const unsigned int errors_map_size
Number of elements in errors_map.