本節介紹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