事件(event)是OpenCL中传递命令状态的对象。命令队列中的命令会生成事件,其他命令在执行之前可能要等待这些事件。用户可以创建定制事件,在宿主机和计算设备之间提供额外的一层控制。在内核中,程序员利用时间可以允许数据的移动与这些数据的相关操作重叠进行。
OpenCL事件是OpenCL中传递命令有关信息的对象。事件的状态描述了相关命令的状态。可以取一下状态值。
- CL_QUEUED:命令已经在命令队列中排队。
- CL_SUBMITTED:入队的命令由宿主机提交给与命令队列相关联的设备。
- CL_RUNNING:计算设备正在执行命令。
- CL_COMPLETE:命令已经完成。
- ERROR_CODE:负值指示遇到某种错误条件。
将命令入队时,通常需要指示一个同步点,在这个同步点之前的所有命令必须先完成,之后的命令才能开始。可以使用clBarrier()函数对队列中的命令知识这样的一个同步点。
cl_int clEnqueueBarrier(
cl_command_queue command_queue)
这个函数只有一个参数,定义了栅栏应用到哪个队列。如果函数成功执行,则命令返回CL_SUCCESS;否则,返回以下某个错误条件。
- CL_INVALID_COMMAND_QUEUE:命令队列不是一个合法的命令队列。
- CL_OUT_OF_RESOURCES,为设备上的OpenCL操作分配内存失败。
- CL_OUT_OF_HOST_MEMORY,为主机上的OpenCL操作分配内存失败。
要定义一个更一般的同步点,OpenCL使用了事件和标志。标志用以下命令设置。
cl_int clEnqueueMarker(
cl_command_queue command_queue,
cl_event *event)
只有所有的命令都入队之后一个,标志命令才能完成。对于一个有序队列,clEnqueueMarker命令的效果就类似于一个栅栏。但与栅栏不同的是,标志命令会返回一个事件。宿主机或其他命令可以等待这个事件,来确保标志命令完成前所有命令都已经入队。
下面这个函数将一个事件等待入队,这会等待一个特定的事件或一组事件完成,之后才会执行将来入队的命令
cl_int clEnqueueWaitForEvents(
cl_command_queue command_queue,
cl_uint num_events,
const cl_event *event_list)
这个命令定义了同步点。这意味着clEnqueueWaitForEvents完成时,内存模型中定义的内存对象更新必须完成,而且后续命令可以依赖于内存对象的一致状态。与event_list中的事件和command_queue关联的上下文必须相同。
2、宿主机生成事件
cl_event clCreateUserEvent(cl_context context,
cl_int *errcode_ret)
此函数可用来创建用户自己的事件对象。有了用户事件,应用就可以让所有入队的命令先等待用户事件完成,然后再由设备来执行。用户事件对象在创建后,其执行状态缺省为CL_SUBMITTED。
对于命令队列中生成的事件,事件的状态是由命令队列控制的。不过,对于用户事件,事件的状态必须通过在宿主机上调用的函数显式控制。
cl_int clSetUserEventStatus(cl_event event,
cl_int execution_status)
这个函数只能调用一次来改变一个用户事件的执行状态,可以为CL_COMPLETE,或者改为一个负值指示存在一个错误。负整数会导致等待这个用户事件的所有入队的命令终止。
3、影响宿主机上执行的事件
cl_int clWaitForEvents(cl_uint num_events,
const cl_event *event_list)
此函数会使主机线程等待event_list中的事件对象所标识的命令完成。对于一个命令而言,如果其执行状态是CL_COMPLETE或负整数,则任务已经完成了。event中的事件充当同步点。
如果event_list中的所有事件的执行状态都是CL_COMPLETE,则clWaitForEvents会返回CL_SUCCESS。否则,返回下列错误码之一:
- CL_INVALID_VALUE,num_events是0或者event_list是NULL。
- CL_INVALID_CONTEXT,event_list中的事件分属于不同的上下文。
- CL_INVALID_EVENT,event_list中的事件对象无效。
- CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST,event_list中的任一事件的执行状态是负整数。
- CL_OUT_OF_RESOURCES,为设备上的OpenCL操作分配内存失败。
- CL_OUT_OF_HOST_MEMORY,为主机上的OpenCL操作分配内存失败。
cl_int clSetEventCallback (
cl_event *event,
cl_int command_exec_callback_type,
void (CL_CALLBACK *pfn_event_notify)(
cl_event event,
cl_int event_command_exec_status,
void *user_data),
void *user_data)
这个函数可以为命令的某个执行状态注册一个用回回调函数。当event所关联的命令的执行状态变成或越过command_exec_status时,所注册的回调函数就会被调用。
调用clSetEventCallback会将用户回调函数注册到event的回调栈上。而对于所注册用户回调函数的调用顺序,则没有定义。
- event是一个事件对象。
- command_exec_callback_type指定命令的执行状态,回调就能注册到此状态上。能注册回调的状态为:CL_SUBMITTED、CL_RUNNING或CL_COMPLETE。不保证按执行状态的变化顺序来调用相应的回调函数。进而,需要注意的是,调用回调时,事件的状态不可能是CL_COMPLETE,但这绝不意味着OpenCL所定义的内存模型和执行模型发生了变化。
- pfn_event_notify即应用所注册的事件回调函数。从函数可能会被OpenCL操作异步调用。应用要保证此函数是线程安全的。此函数的参数为:
- event即此函数所关注的事件。
- event_command_exec_status即此函数所关注的命令执行状态。如果是由于命令异常终止而调用的此函数,那么传递给event_command_exec_status的将是相应的错误码。
- user_data指向用户提供的数据。
- user_data将在用户调用pfn_event_notify时作为其参数user_data传入。user_data可以是NULL。