Skip to content

Instantly share code, notes, and snippets.

@allanmac
Last active Oct 26, 2020
Embed
What would you like to do?
Macros for neatly error checking OpenCL API functions.

Simply adding two parentheses cl(...) gives you error checking for OpenCL API functions that return a cl_int error code.

The second cl_ok(err) macro is for error checking API functions that initialize their error code as an argument.

The header also includes a useful function for converting OpenCL errors to strings:

char const * clGetErrorString(cl_int const err);

Example 1:


cl(Finish(command_queue));

cl_ulong start_time,end_time;

cl(GetEventProfilingInfo(start == NULL ? end : start,
                         CL_PROFILING_COMMAND_START,sizeof(cl_ulong),&start_time,NULL));
cl(GetEventProfilingInfo(end,
                         CL_PROFILING_COMMAND_END,  sizeof(cl_ulong),&end_time,  NULL));

elapsed_ns += end_time - start_time;

if (start != NULL)
  cl(ReleaseEvent(start));

cl(ReleaseEvent(end));

Example 2:


cl_program program = clCreateProgramWithSource(context,
                                               1,
                                               strings,
                                               strings_sizeof,
                                               &err);
cl_ok(err);

char const * const options = 
  "-cl-std=CL2.0 -cl-fast-relaxed-math "
  "-cl-no-signed-zeros -cl-mad-enable "
  "-cl-denorms-are-zero "
  "-cl-kernel-arg-info";

cl(BuildProgram(program,
                1,
                &device_id,
                options,
                NULL,
                NULL));

//
//
//
#include <stdlib.h>
#include <stdio.h>
//
//
//
#include "assert_cl.h"
//
//
//
#define CL_ERR_TO_STR(err) case err: return #err
//
//
//
char const *
clGetErrorString(cl_int const err)
{
switch(err)
{
CL_ERR_TO_STR(CL_SUCCESS);
CL_ERR_TO_STR(CL_DEVICE_NOT_FOUND);
CL_ERR_TO_STR(CL_DEVICE_NOT_AVAILABLE);
CL_ERR_TO_STR(CL_COMPILER_NOT_AVAILABLE);
CL_ERR_TO_STR(CL_MEM_OBJECT_ALLOCATION_FAILURE);
CL_ERR_TO_STR(CL_OUT_OF_RESOURCES);
CL_ERR_TO_STR(CL_OUT_OF_HOST_MEMORY);
CL_ERR_TO_STR(CL_PROFILING_INFO_NOT_AVAILABLE);
CL_ERR_TO_STR(CL_MEM_COPY_OVERLAP);
CL_ERR_TO_STR(CL_IMAGE_FORMAT_MISMATCH);
CL_ERR_TO_STR(CL_IMAGE_FORMAT_NOT_SUPPORTED);
CL_ERR_TO_STR(CL_BUILD_PROGRAM_FAILURE);
CL_ERR_TO_STR(CL_MAP_FAILURE);
CL_ERR_TO_STR(CL_MISALIGNED_SUB_BUFFER_OFFSET);
CL_ERR_TO_STR(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST);
CL_ERR_TO_STR(CL_COMPILE_PROGRAM_FAILURE);
CL_ERR_TO_STR(CL_LINKER_NOT_AVAILABLE);
CL_ERR_TO_STR(CL_LINK_PROGRAM_FAILURE);
CL_ERR_TO_STR(CL_DEVICE_PARTITION_FAILED);
CL_ERR_TO_STR(CL_KERNEL_ARG_INFO_NOT_AVAILABLE);
CL_ERR_TO_STR(CL_INVALID_VALUE);
CL_ERR_TO_STR(CL_INVALID_DEVICE_TYPE);
CL_ERR_TO_STR(CL_INVALID_PLATFORM);
CL_ERR_TO_STR(CL_INVALID_DEVICE);
CL_ERR_TO_STR(CL_INVALID_CONTEXT);
CL_ERR_TO_STR(CL_INVALID_QUEUE_PROPERTIES);
CL_ERR_TO_STR(CL_INVALID_COMMAND_QUEUE);
CL_ERR_TO_STR(CL_INVALID_HOST_PTR);
CL_ERR_TO_STR(CL_INVALID_MEM_OBJECT);
CL_ERR_TO_STR(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR);
CL_ERR_TO_STR(CL_INVALID_IMAGE_SIZE);
CL_ERR_TO_STR(CL_INVALID_SAMPLER);
CL_ERR_TO_STR(CL_INVALID_BINARY);
CL_ERR_TO_STR(CL_INVALID_BUILD_OPTIONS);
CL_ERR_TO_STR(CL_INVALID_PROGRAM);
CL_ERR_TO_STR(CL_INVALID_PROGRAM_EXECUTABLE);
CL_ERR_TO_STR(CL_INVALID_KERNEL_NAME);
CL_ERR_TO_STR(CL_INVALID_KERNEL_DEFINITION);
CL_ERR_TO_STR(CL_INVALID_KERNEL);
CL_ERR_TO_STR(CL_INVALID_ARG_INDEX);
CL_ERR_TO_STR(CL_INVALID_ARG_VALUE);
CL_ERR_TO_STR(CL_INVALID_ARG_SIZE);
CL_ERR_TO_STR(CL_INVALID_KERNEL_ARGS);
CL_ERR_TO_STR(CL_INVALID_WORK_DIMENSION);
CL_ERR_TO_STR(CL_INVALID_WORK_GROUP_SIZE);
CL_ERR_TO_STR(CL_INVALID_WORK_ITEM_SIZE);
CL_ERR_TO_STR(CL_INVALID_GLOBAL_OFFSET);
CL_ERR_TO_STR(CL_INVALID_EVENT_WAIT_LIST);
CL_ERR_TO_STR(CL_INVALID_EVENT);
CL_ERR_TO_STR(CL_INVALID_OPERATION);
CL_ERR_TO_STR(CL_INVALID_GL_OBJECT);
CL_ERR_TO_STR(CL_INVALID_BUFFER_SIZE);
CL_ERR_TO_STR(CL_INVALID_MIP_LEVEL);
CL_ERR_TO_STR(CL_INVALID_GLOBAL_WORK_SIZE);
CL_ERR_TO_STR(CL_INVALID_PROPERTY);
CL_ERR_TO_STR(CL_INVALID_IMAGE_DESCRIPTOR);
CL_ERR_TO_STR(CL_INVALID_COMPILER_OPTIONS);
CL_ERR_TO_STR(CL_INVALID_LINKER_OPTIONS);
CL_ERR_TO_STR(CL_INVALID_DEVICE_PARTITION_COUNT);
CL_ERR_TO_STR(CL_INVALID_PIPE_SIZE);
CL_ERR_TO_STR(CL_INVALID_DEVICE_QUEUE);
default:
return "UNKNOWN ERROR CODE";
}
}
//
//
//
cl_int
cl_assert(cl_int const code, char const * const file, int const line, bool const abort)
{
if (code != CL_SUCCESS)
{
char const * const err_str = clGetErrorString(code);
fprintf(stderr,
"\"%s\", line %d: cl_assert (%d) = \"%s\"",
file,line,code,err_str);
if (abort)
{
// stop profiling and reset device here if necessary
exit(code);
}
}
return code;
}
//
//
//
//
//
//
#pragma once
//
//
//
#include <CL/opencl.h>
#include <stdbool.h>
//
//
//
char const * clGetErrorString(cl_int const err);
//
//
//
cl_int cl_assert(cl_int const code, char const * const file, int const line, bool const abort);
#define cl(...) cl_assert((cl##__VA_ARGS__), __FILE__, __LINE__, true);
#define cl_ok(err) cl_assert(err, __FILE__, __LINE__, true);
//
//
//
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment