OpenCL編程之同步問題:事件

事件(event)是OpenCL中傳遞命令狀態的對象。命令隊列中的命令會生成事件,其他命令在執行之前可能要等待這些事件。用戶可以創建定製事件,在宿主機和計算設備之間提供額外的一層控制。在內核中,程序員利用時間可以允許數據的移動與這些數據的相關操作重疊進行。

OpenCL事件是OpenCL中傳遞命令有關信息的對象。事件的狀態描述了相關命令的狀態。可以取一下狀態值。
  • CL_QUEUED:命令已經在命令隊列中排隊。
  • CL_SUBMITTED:入隊的命令由宿主機提交給與命令隊列相關聯的設備。
  • CL_RUNNING:計算設備正在執行命令。
  • CL_COMPLETE:命令已經完成。
  • ERROR_CODE:負值指示遇到某種錯誤條件。
將命令入隊時,通常需要指示一個同步點,在這個同步點之前的所有命令必須先完成,之後的命令才能開始。可以使用clBarrier()函數對隊列中的命令知識這樣的一個同步點。
  1. cl_int clEnqueueBarrier(
  2. cl_command_queue command_queue)
這個函數只有一個參數,定義了柵欄應用到哪個隊列。如果函數成功執行,則命令返回CL_SUCCESS;否則,返回以下某個錯誤條件。
  • CL_INVALID_COMMAND_QUEUE:命令隊列不是一個合法的命令隊列。
  • CL_OUT_OF_RESOURCES,爲設備上的OpenCL操作分配內存失敗。
  • CL_OUT_OF_HOST_MEMORY,爲主機上的OpenCL操作分配內存失敗。
要定義一個更一般的同步點,OpenCL使用了事件和標誌。標誌用以下命令設置。
  1. cl_int clEnqueueMarker(
  2. cl_command_queue command_queue,
  3. cl_event *event)
只有所有的命令都入隊之後一個,標誌命令才能完成。對於一個有序隊列,clEnqueueMarker命令的效果就類似於一個柵欄。但與柵欄不同的是,標誌命令會返回一個事件。宿主機或其他命令可以等待這個事件,來確保標誌命令完成前所有命令都已經入隊。

下面這個函數將一個事件等待入隊,這會等待一個特定的事件或一組事件完成,之後纔會執行將來入隊的命令
  1. cl_int clEnqueueWaitForEvents(
  2. cl_command_queue command_queue,
  3. cl_uint num_events,
  4. const cl_event *event_list)
這個命令定義了同步點。這意味着clEnqueueWaitForEvents完成時,內存模型中定義的內存對象更新必須完成,而且後續命令可以依賴於內存對象的一致狀態。與event_list中的事件和command_queue關聯的上下文必須相同。


2、宿主機生成事件
  1. cl_event clCreateUserEvent(cl_context context,
  2. cl_int *errcode_ret)
此函數可用來創建用戶自己的事件對象。有了用戶事件,應用就可以讓所有入隊的命令先等待用戶事件完成,然後再由設備來執行。用戶事件對象在創建後,其執行狀態缺省爲CL_SUBMITTED。

對於命令隊列中生成的事件,事件的狀態是由命令隊列控制的。不過,對於用戶事件,事件的狀態必須通過在宿主機上調用的函數顯式控制。
  1. cl_int clSetUserEventStatus(cl_event event,
  2. cl_int execution_status)
這個函數只能調用一次來改變一個用戶事件的執行狀態,可以爲CL_COMPLETE,或者改爲一個負值指示存在一個錯誤。負整數會導致等待這個用戶事件的所有入隊的命令終止。

3、影響宿主機上執行的事件
  1. cl_int clWaitForEvents(cl_uint num_events,
  2. 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操作分配內存失敗。
事件還可以通過回調機制與宿主機上的函數交互。回調就是代表應用程序異步調用的函數。程序員可以通過以下函數將一個回調函數與任意事件關聯。
  1. cl_int clSetEventCallback (
  2. cl_event *event,
  3. cl_int command_exec_callback_type,
  4. void (CL_CALLBACK *pfn_event_notify)(
  5. cl_event event,
  6. cl_int event_command_exec_status,
  7. void *user_data),
  8. 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。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章