Skip to content

Instantly share code, notes, and snippets.

@allanmac
Last active June 10, 2023 11:11
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save allanmac/9328bb2d6a99b86883195f8f78fd1b93 to your computer and use it in GitHub Desktop.
Save allanmac/9328bb2d6a99b86883195f8f78fd1b93 to your computer and use it in GitHub Desktop.
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