RustiCL: deadlock when calling clGetProfilingInfo() on callbacks
If I call clGetProfilingInfo()
on a callback (registered with clSetEventCallback()
), the program hangs. I am enclosing a simple demonstrator below. The same test works on PoCL (although it gives zeros on the callback, and apparently good timestamps on the main thread).
Bonus track: If one profiles on the main thread an event created with clEnqueueMarkerWithWaitList()
, it gives all zeros. You can test that commenting lines 17-30 of the demonstrator.
#include <iostream>
#include <cassert>
#include <CL/cl.h>
#define PLATFORM 0
#define DEVICE 0
void CL_CALLBACK
cb(cl_event trigger, cl_int event_command_status, void* user_data)
{
cl_int err_code;
// Not even one of the following profilings is working. But if you comment
// this block of code the profilings on the main thread are working just
// fine
std::cout << "Profiling on the cb..." << std::endl;
for (auto info : {CL_PROFILING_COMMAND_QUEUED,
CL_PROFILING_COMMAND_SUBMIT,
CL_PROFILING_COMMAND_START,
CL_PROFILING_COMMAND_END,
CL_PROFILING_COMMAND_COMPLETE})
{
cl_ulong timer;
err_code = clGetEventProfilingInfo(trigger,
info,
sizeof(cl_ulong),
&timer,
NULL);
std::cout << "\t" << info << " = " << timer << std::endl << std::flush;
}
cl_event event = (cl_event)user_data;
err_code = clSetUserEventStatus(event, CL_COMPLETE);
assert(err_code == CL_SUCCESS);
std::cout << "exiting cb..." << std::endl;
}
int main(int argc, char *argv[])
{
cl_int err_code;
cl_uint n;
// Get the platform
err_code = clGetPlatformIDs(0, NULL, &n);
assert(err_code == CL_SUCCESS);
assert(PLATFORM < n);
cl_platform_id* platforms = (cl_platform_id*)malloc(
n * sizeof(cl_platform_id));
assert(platforms);
err_code = clGetPlatformIDs(n, platforms, NULL);
assert(err_code == CL_SUCCESS);
cl_platform_id platform = platforms[PLATFORM];
free(platforms);
// Get the device
err_code = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 0, NULL, &n);
assert(err_code == CL_SUCCESS);
assert(DEVICE < n);
cl_device_id* devices = (cl_device_id*)malloc(n * sizeof(cl_device_id));
assert(devices);
err_code = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, n, devices, NULL);
assert(err_code == CL_SUCCESS);
cl_device_id device = devices[DEVICE];
free(devices);
// Create a context
cl_context context = clCreateContext(
NULL, 1, &device, NULL, NULL, &err_code);
assert(err_code == CL_SUCCESS);
assert(context);
// Create a command_queue
const cl_queue_properties properties[3] = {
CL_QUEUE_PROPERTIES, CL_QUEUE_PROFILING_ENABLE,
0
};
cl_command_queue queue = clCreateCommandQueueWithProperties(
context, device, properties, &err_code);
assert(err_code == CL_SUCCESS);
assert(queue);
// Create an user event
cl_event event_wait = clCreateUserEvent(context, &err_code);
assert(err_code == CL_SUCCESS);
assert(event_wait);
// Create an user event to be set as complete by the callback
cl_event finish = clCreateUserEvent(context, &err_code);
assert(err_code == CL_SUCCESS);
assert(finish);
// Create the callback trigger synced with the first user event
cl_event trigger;
err_code = clEnqueueMarkerWithWaitList(queue, 0, NULL, &trigger);
assert(err_code == CL_SUCCESS);
// Register the callback, in which we are calling clGetEventProfilingInfo()
err_code = clSetEventCallback(
trigger, CL_COMPLETE, cb, (void*)finish);
assert(err_code == CL_SUCCESS);
// Launch everything
err_code = clSetUserEventStatus(event_wait, CL_COMPLETE);
assert(err_code == CL_SUCCESS);
clFlush(queue);
// Wait for the callback
std::cout << "Waiting..." << std::endl;
err_code = clWaitForEvents(1, &finish);
assert(err_code == CL_SUCCESS);
// The following profilings are working (returning zeros though)
std::cout << "Profiling on the main thread..." << std::endl;
for (auto info : {CL_PROFILING_COMMAND_QUEUED,
CL_PROFILING_COMMAND_SUBMIT,
CL_PROFILING_COMMAND_START,
CL_PROFILING_COMMAND_END,
CL_PROFILING_COMMAND_COMPLETE})
{
cl_ulong timer;
err_code = clGetEventProfilingInfo(trigger,
info,
sizeof(cl_ulong),
&timer,
NULL);
std::cout << "\t" << info << " = " << timer << std::endl << std::flush;
}
std::cout << "All done!" << std::endl;
// Clean up
err_code = clReleaseEvent(finish);
assert(err_code == CL_SUCCESS);
err_code = clReleaseEvent(trigger);
assert(err_code == CL_SUCCESS);
err_code = clReleaseEvent(event_wait);
assert(err_code == CL_SUCCESS);
err_code = clReleaseCommandQueue(queue);
assert(err_code == CL_SUCCESS);
err_code = clReleaseContext(context);
assert(err_code == CL_SUCCESS);
}
Edited by Jose Luis Cercos-Pita