本节介绍OpenCL的事件的相关知识。
由上一节咱们已经清楚了宿主机经过命令队列向计算设备传递命令。计算设备计算后返回。可是宿主机须要管理多个计算设备,多个命令队列。那么宿主机是如何管理、调度这些对象的呢。没错,就是事件(event)。安全
事件是与命令的状态相关联的对象。命令队列中的命令会产生事件,其余命令在执行以前须要等待某个事件。如咱们下面条以前须要查看水开了没有,那么水开了
就是一个事件。异步
根据场景的不一样,能够分为内核端事件和宿主机端事件:async
我的自扫门前雪
的意味,由于人民内部矛盾内部解决嘛
)。 同时事件还能够划分为命令事件
和用户自定义事件
。ide
事件在命令之间传递状态信息。命令的状态即事件的值能够取如下:函数
建立事件的方法有不少,最多见的仍是命令在状态发生变化时。以下面的命令是将内核加入队列的API,那么就会产生一个CL_QUEUED
命令。ui
cl_int clEnqueueNDRangeKernel( cl_command_queue command_queue, cl_kernel kernel, cl_unit work_dim, const size_t* global_work_offset, const size_t* global_work_size, const size_t* local_work_size, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event )
咱们着重关注一下后面三个参数:线程
CL_QUEUED
,以后在执行的时候会赋值为CL_RUNNING
等等。再看一下多个事件之间的联系的一个示例:指针
cl_event k_events[2]; //定义两个事件 clEnqueueNDRangeKernel(command1, .... , 0, NULL, &k_events[0]); //将第一个命令加入队列,会对k_events[0]赋值,指向以前不须要等待任何事件 clEnqueueNDRangeKernel(command2, ...., 0, NULL, &k_events[0]); //同上 clEnqueueNDRangeKernel(command3, ...., 2,&k_events, NULL) //执行这条命令时会等待前面的两个命令
命令事件主要在命令队列中产生,影响同一个上下文的设备。若是咱们须要与其余上下文进行同步,就须要使用到用户自定义事件:code
cl_event clCreateUserEvent( cl_context context, //指定上下文 cl_uint* errcode_ret //该函数所关联的错误值 )
若是建立成功,errcode_ret会被赋值为CL_SUCCESS
或者错误时,赋值为一下的值:对象
以后咱们就能够在各个处理函数中设置返回的事件的值:
cl_int clSetUserEventStatus( cl_event event, //具体事件值 cl_int execution_status //指向状态 )
上面已经说过了用户自定义事件的设置,那么命令事件的管理又是经过那些API的呢?
clGetEventStatus clRetainEvent //增长引用计数,即获得事件 cl_ReleaseEvent //减小引用计数
固然若是须要获取事件的更详细的信息,须要用到:
cl_int clGetEventInfo( cl_event event, //具体事件 cl_event_info param_name, //查询的信息,如命令队列,或者上下文 size_t param_value_size, //参数大小, void* param_value, //指向的结果的指针 size_t param_value_size_ret //返回结果的大小 )
事件是OpenCL中为命令指定明确顺序约束的机制。不过事件不能跨上下文,跨上下文边界时,只有一种选择,就是让宿主机帮忙等待一个事件,而后使用用户事件触发另外一个上下文命令的执行。总而言之,因为事件不能跨上下文,因此宿主机必须表明两个命令队列在两个上下文之间管理事件。
同时,事件还可使用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_t async_work_group_copy() event_t async_work_group_strided_copy event_t wait_group_events
会在后面的章节有所介绍。
版权声明:本文为博主原创文章,转载需声明为转载内容并添加原文地址。
原文地址:http://coderdock.com