Function to get human readable error messages

Hi all,
I’ve been through the 1.1 specification and I see that I’m still lacking one feature : how to print/get a message describing (even tersly) the last error. The models could be based on the perror()/strerror() calls (clPError() / clStrError()).

I had to duplicate the cl.h section about error codes to build the appropriate strings to issue human readable messages. I wish it was provided as a standard (mandatory) function so that whatever the implementation is (or will be), we can get the actual message.

This is important for high quality production codes.
Thanks.
Guillaume

My memory could be failing, but I seem to recall that this was discussed and rejected. It’s something that the application can do easily and driver developers prefer to focus on actually writing drivers.

I have found that this helps.
export CL_LOG_ERRORS=“stdout”
(or stderr etc…)

Also, owning a copy of the error codes and their integer values has been immensely useful. Finally, I would agree with having better description of errors. Something that invalidates my command queue because of a logical error in my kernel can be tricky to debug.

This feature is a library one not a driver issue. What I really want to avoid is to duplicate error messages across codes especially the “system” ones.
Do you think it is wise to replicate the following code millions of time when it could be done once for good in the vendors implementations ?
Should any of the values change for good reasons and your code is wrong.

Guillaume

void
oclPrintErr(cl_int rc, const char *msg, const char *file, const int line)
{
char message[1000];
if (rc != CL_SUCCESS) {
strcpy(message, “”);
switch (rc) {
case 0:
strcat(message, “CL_SUCCESS”);;
break;
case -1:
strcat(message, “CL_DEVICE_NOT_FOUND”);;
break;
case -2:
strcat(message, “CL_DEVICE_NOT_AVAILABLE”);;
break;
case -3:
strcat(message, “CL_COMPILER_NOT_AVAILABLE”);;
break;
case -4:
strcat(message, “CL_MEM_OBJECT_ALLOCATION_FAILURE”);;
break;
case -5:
strcat(message, “CL_OUT_OF_RESOURCES”);;
break;
case -6:
strcat(message, “CL_OUT_OF_HOST_MEMORY”);;
break;
case -7:
strcat(message, “CL_PROFILING_INFO_NOT_AVAILABLE”);;
break;
case -8:
strcat(message, “CL_MEM_COPY_OVERLAP”);;
break;
case -9:
strcat(message, “CL_IMAGE_FORMAT_MISMATCH”);;
break;
case -10:
strcat(message, “CL_IMAGE_FORMAT_NOT_SUPPORTED”);;
break;
case -11:
strcat(message, “CL_BUILD_PROGRAM_FAILURE”);;
break;
case -12:
strcat(message, “CL_MAP_FAILURE”);;
break;
case -30:
strcat(message, “CL_INVALID_VALUE”);;
break;
case -31:
strcat(message, “CL_INVALID_DEVICE_TYPE”);;
break;
case -32:
strcat(message, “CL_INVALID_PLATFORM”);;
break;
case -33:
strcat(message, “CL_INVALID_DEVICE”);;
break;
case -34:
strcat(message, “CL_INVALID_CONTEXT”);;
break;
case -35:
strcat(message, “CL_INVALID_QUEUE_PROPERTIES”);;
break;
case -36:
strcat(message, “CL_INVALID_COMMAND_QUEUE”);;
break;
case -37:
strcat(message, “CL_INVALID_HOST_PTR”);;
break;
case -38:
strcat(message, “CL_INVALID_MEM_OBJECT”);;
break;
case -39:
strcat(message, “CL_INVALID_IMAGE_FORMAT_DESCRIPTOR”);;
break;
case -40:
strcat(message, “CL_INVALID_IMAGE_SIZE”);;
break;
case -41:
strcat(message, “CL_INVALID_SAMPLER”);;
break;
case -42:
strcat(message, “CL_INVALID_BINARY”);;
break;
case -43:
strcat(message, “CL_INVALID_BUILD_OPTIONS”);;
break;
case -44:
strcat(message, “CL_INVALID_PROGRAM”);;
break;
case -45:
strcat(message, “CL_INVALID_PROGRAM_EXECUTABLE”);;
break;
case -46:
strcat(message, “CL_INVALID_KERNEL_NAME”);;
break;
case -47:
strcat(message, “CL_INVALID_KERNEL_DEFINITION”);;
break;
case -48:
strcat(message, “CL_INVALID_KERNEL”);;
break;
case -49:
strcat(message, “CL_INVALID_ARG_INDEX”);;
break;
case -50:
strcat(message, “CL_INVALID_ARG_VALUE”);;
break;
case -51:
strcat(message, “CL_INVALID_ARG_SIZE”);;
break;
case -52:
strcat(message, “CL_INVALID_KERNEL_ARGS”);;
break;
case -53:
strcat(message, “CL_INVALID_WORK_DIMENSION”);;
break;
case -54:
strcat(message, “CL_INVALID_WORK_GROUP_SIZE”);;
break;
case -55:
strcat(message, “CL_INVALID_WORK_ITEM_SIZE”);;
break;
case -56:
strcat(message, “CL_INVALID_GLOBAL_OFFSET”);;
break;
case -57:
strcat(message, “CL_INVALID_EVENT_WAIT_LIST”);;
break;
case -58:
strcat(message, “CL_INVALID_EVENT”);;
break;
case -59:
strcat(message, “CL_INVALID_OPERATION”);;
break;
case -60:
strcat(message, “CL_INVALID_GL_OBJECT”);;
break;
case -61:
strcat(message, “CL_INVALID_BUFFER_SIZE”);;
break;
case -62:
strcat(message, “CL_INVALID_MIP_LEVEL”);;
break;
case -63:
strcat(message, “CL_INVALID_GLOBAL_WORK_SIZE”);;
break;
case -1001:
strcat(message, “CL_PLATFORM_NOT_FOUND_KHR”);;
break;
default:
strcat(message, “unknown code”);
}
fprintf(stderr, "Error %d <%s> (%s) [f=%s l=%d]
", rc, message, msg, file, line);
}
}

You may prefer an alternative implementation:


void
oclPrintErr(cl_int errcode, const char *msg, const char *file, const int line)
{
const char* errname = NULL;

switch (errcode)
{
case CL_SUCCESS: errname = "CL_SUCCESS"; break;
case CL_DEVICE_NOT_FOUND: errname = "CL_DEVICE_NOT_FOUND"; break;
...etc...
}
fprintf(stderr, "Error %d <%s> (%s) [f=%s l=%d]
", errcode, errname, msg, file, line);

Also, have you considered using the notification callback in clCreateContext?