[Beignet] [PATCH V1 1/2] add [opencl-1.2] API clEnqueueBarrierWithWaitList.

xionghu.luo at intel.com xionghu.luo at intel.com
Mon May 5 20:22:49 PDT 2014


From: Luo <xionghu.luo at intel.com>

This command blocks command execution, that is, any following commands
enqueued after it do not execute until it completes;
API clEnqueueMarkerWithWaitList patch didn't push the latest, update in
 this patch.
---
 src/cl_api.c           |  19 +++++-
 src/cl_command_queue.c |  66 +++++++++++++++++--
 src/cl_command_queue.h |   9 ++-
 src/cl_enqueue.h       |   1 +
 src/cl_event.c         | 167 ++++++++++++++++++++++++++++++++-----------------
 src/cl_event.h         |   6 ++
 6 files changed, 202 insertions(+), 66 deletions(-)

diff --git a/src/cl_api.c b/src/cl_api.c
index 9c22819..ad70b65 100644
--- a/src/cl_api.c
+++ b/src/cl_api.c
@@ -2753,8 +2753,25 @@ clEnqueueBarrier(cl_command_queue  command_queue)
 {
   cl_int err = CL_SUCCESS;
   CHECK_QUEUE(command_queue);
-  cl_command_queue_set_barrier(command_queue);
 
+  cl_event_barrier_with_wait_list(command_queue, 0, NULL, NULL);
+
+error:
+  return err;
+}
+
+cl_int
+clEnqueueBarrierWithWaitList(cl_command_queue command_queue,
+    cl_uint num_events_in_wait_list,
+    const cl_event *event_wait_list,
+    cl_event *event)
+{
+  cl_int err = CL_SUCCESS;
+  CHECK_QUEUE(command_queue);
+
+  TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, command_queue->ctx);
+
+  cl_event_barrier_with_wait_list(command_queue, num_events_in_wait_list, event_wait_list, event);
 error:
   return err;
 }
diff --git a/src/cl_command_queue.c b/src/cl_command_queue.c
index 6a699c0..c754ad5 100644
--- a/src/cl_command_queue.c
+++ b/src/cl_command_queue.c
@@ -492,18 +492,74 @@ cl_command_queue_remove_event(cl_command_queue queue, cl_event event)
   if(i == queue->wait_events_num)
     return;
 
-  if(queue->barrier_index >= i)
-    queue->barrier_index -= 1;
-
   for(; i<queue->wait_events_num-1; i++) {
     queue->wait_events[i] = queue->wait_events[i+1];
   }
   queue->wait_events_num -= 1;
 }
 
+#define DEFAULT_WAIT_EVENTS_SIZE  16
 LOCAL void
-cl_command_queue_set_barrier(cl_command_queue queue)
+cl_command_queue_insert_barrier_event(cl_command_queue queue, cl_event event)
 {
-    queue->barrier_index = queue->wait_events_num;
+  cl_int i=0;
+  cl_event *new_list;
+
+  assert(queue != NULL);
+  if(queue->barrier_events == NULL) {
+    queue->barrier_events_size = DEFAULT_WAIT_EVENTS_SIZE;
+    TRY_ALLOC_NO_ERR (queue->barrier_events, CALLOC_ARRAY(cl_event, queue->barrier_events_size));
+  }
+
+  for(i=0; i<queue->barrier_events_num; i++) {
+    if(queue->barrier_events[i] == event)
+      return;   //is in the barrier_events, need to insert
+  }
+
+  if(queue->barrier_events_num < queue->barrier_events_size) {
+    queue->barrier_events[queue->barrier_events_num++] = event;
+    return;
+  }
+
+  //barrier_events_num == barrier_events_size, array is full
+  queue->barrier_events_size *= 2;
+  TRY_ALLOC_NO_ERR (new_list, CALLOC_ARRAY(cl_event, queue->barrier_events_size));
+  memcpy(new_list, queue->barrier_events, sizeof(cl_event)*queue->barrier_events_num);
+  cl_free(queue->barrier_events);
+  queue->barrier_events = new_list;
+  queue->barrier_events[queue->barrier_events_num++] = event;
+  return;
+
+exit:
+  return;
+error:
+  if(queue->barrier_events)
+    cl_free(queue->barrier_events);
+  queue->barrier_events = NULL;
+  queue->barrier_events_size = 0;
+  queue->barrier_events_num = 0;
+  goto exit;
+
 }
 
+LOCAL void
+cl_command_queue_remove_barrier_event(cl_command_queue queue, cl_event event)
+{
+  cl_int i=0;
+
+  if(queue->barrier_events_num == 0)
+    return;
+
+  for(i=0; i<queue->barrier_events_num; i++) {
+    if(queue->barrier_events[i] == event)
+      break;
+  }
+
+  if(i == queue->barrier_events_num)
+    return;
+
+  for(; i<queue->barrier_events_num-1; i++) {
+    queue->barrier_events[i] = queue->barrier_events[i+1];
+  }
+  queue->barrier_events_num -= 1;
+}
diff --git a/src/cl_command_queue.h b/src/cl_command_queue.h
index 40c272c..b79d63a 100644
--- a/src/cl_command_queue.h
+++ b/src/cl_command_queue.h
@@ -34,10 +34,12 @@ struct _cl_command_queue {
   uint64_t magic;                      /* To identify it as a command queue */
   volatile int ref_n;                  /* We reference count this object */
   cl_context ctx;                      /* Its parent context */
+  cl_event* barrier_events;               /* Point to array of non-complete user events that block this command queue */
+  cl_int    barrier_events_num;           /* Number of Non-complete user events */
+  cl_int    barrier_events_size;          /* The size of array that wait_events point to */
   cl_event* wait_events;               /* Point to array of non-complete user events that block this command queue */
   cl_int    wait_events_num;           /* Number of Non-complete user events */
   cl_int    wait_events_size;          /* The size of array that wait_events point to */
-  cl_int    barrier_index;             /* Indicate event count in wait_events as barrier events */
   cl_event  last_event;                /* The last event in the queue, for enqueue mark used */
   cl_command_queue_properties  props;  /* Queue properties */
   cl_command_queue prev, next;         /* We chain the command queues together */
@@ -95,8 +97,9 @@ extern void cl_command_queue_insert_event(cl_command_queue, cl_event);
 /* Remove a user event from command's wait_events */
 extern void cl_command_queue_remove_event(cl_command_queue, cl_event);
 
-/* Set the barrier index */
-extern void cl_command_queue_set_barrier(cl_command_queue);
+extern void cl_command_queue_insert_barrier_event(cl_command_queue queue, cl_event event);
+
+extern void cl_command_queue_remove_barrier_event(cl_command_queue queue, cl_event event);
 
 #endif /* __CL_COMMAND_QUEUE_H__ */
 
diff --git a/src/cl_enqueue.h b/src/cl_enqueue.h
index cb612eb..3593f01 100644
--- a/src/cl_enqueue.h
+++ b/src/cl_enqueue.h
@@ -41,6 +41,7 @@ typedef enum {
   EnqueueNDRangeKernel,
   EnqueueNativeKernel,
   EnqueueMarker,
+  EnqueueBarrier,
   EnqueueFillBuffer,
   EnqueueInvalid
 } enqueue_type;
diff --git a/src/cl_event.c b/src/cl_event.c
index 1230581..a94541a 100644
--- a/src/cl_event.c
+++ b/src/cl_event.c
@@ -231,7 +231,14 @@ cl_int cl_event_wait_events(cl_uint num_events_in_wait_list, const cl_event *eve
     }
   }
 
-  if(queue && queue->barrier_index > 0) {
+  if(queue && queue->barrier_events_num ) {
+    if(num_events_in_wait_list == 0){
+      for(j=0; j<queue->wait_events_num; j++)
+        cl_event_add_ref(queue->wait_events[j]);  //add defer enqueue's wait event reference
+    }else{
+      for(j=0; j<num_events_in_wait_list; j++)
+        cl_event_add_ref(event_wait_list[j]);  //add defer enqueue's wait event reference
+    }
     return CL_ENQUEUE_EXECUTE_DEFER;
   }
 
@@ -259,6 +266,7 @@ void cl_event_new_enqueue_callback(cl_event event,
   user_event *user_events, *u_ev;
   cl_command_queue queue = event->queue;
   cl_int i;
+  cl_int err = CL_SUCCESS;
   GET_QUEUE_THREAD_GPGPU(data->queue);
 
   /* Allocate and initialize the structure itself */
@@ -271,8 +279,8 @@ void cl_event_new_enqueue_callback(cl_event event,
   cb->next = NULL;
   cb->wait_user_events = NULL;
 
-  if(queue && queue->barrier_index > 0) {
-    for(i=0; i<queue->barrier_index; i++) {
+  if(queue && queue->barrier_events_num > 0) {
+    for(i=0; i<queue->barrier_events_num; i++) {
       /* Insert the enqueue_callback to user event list */
       node = queue->wait_events[i]->waits_head;
       if(node == NULL)
@@ -286,10 +294,7 @@ void cl_event_new_enqueue_callback(cl_event event,
       }
 
       /* Insert the user event to enqueue_callback's wait_user_events */
-      TRY_ALLOC_NO_ERR (u_ev, CALLOC(user_event));
-      u_ev->event = queue->wait_events[i];
-      u_ev->next = cb->wait_user_events;
-      cb->wait_user_events = u_ev;
+      TRY(cl_event_insert_user_event, &cb->wait_user_events, queue->wait_events[i]);
     }
   }
 
@@ -311,11 +316,11 @@ void cl_event_new_enqueue_callback(cl_event event,
         node->next = cb;
       }
       /* Insert the user event to enqueue_callback's wait_user_events */
-      TRY_ALLOC_NO_ERR (u_ev, CALLOC(user_event));
-      u_ev->event = event_wait_list[i];
-      u_ev->next = cb->wait_user_events;
-      cb->wait_user_events = u_ev;
+      TRY(cl_event_insert_user_event, &cb->wait_user_events, event_wait_list[i]);
       cl_command_queue_insert_event(event->queue, event_wait_list[i]);
+      if(data->type == EnqueueBarrier){
+        cl_command_queue_insert_barrier_event(event->queue, event_wait_list[i]);
+      }
     } else if(event_wait_list[i]->enqueue_cb != NULL) {
       user_events = event_wait_list[i]->enqueue_cb->wait_user_events;
       while(user_events != NULL) {
@@ -334,11 +339,11 @@ void cl_event_new_enqueue_callback(cl_event event,
         }
 
         /* Insert the user event to enqueue_callback's wait_user_events */
-        TRY_ALLOC_NO_ERR (u_ev, CALLOC(user_event));
-        u_ev->event = user_events->event;
-        u_ev->next = cb->wait_user_events;
-        cb->wait_user_events = u_ev;
+        TRY(cl_event_insert_user_event, &cb->wait_user_events, user_events->event);
         cl_command_queue_insert_event(event->queue, user_events->event);
+        if(data->type == EnqueueBarrier){
+          cl_command_queue_insert_barrier_event(event->queue, user_events->event);
+        }
         user_events = user_events->next;
       }
     }
@@ -369,7 +374,6 @@ error:
 void cl_event_set_status(cl_event event, cl_int status)
 {
   user_callback *user_cb;
-  user_event    *u_ev;
   cl_int ret, i;
   cl_event evt;
 
@@ -426,29 +430,7 @@ void cl_event_set_status(cl_event event, cl_int status)
   enqueue_callback *cb, *enqueue_cb = event->waits_head;
   while(enqueue_cb) {
     /* Remove this user event in enqueue_cb, update the header if needed. */
-    u_ev = enqueue_cb->wait_user_events;
-    user_event * u_prev = NULL;
-    user_event *tmp =NULL;
-    while(u_ev) {
-      if(u_ev && u_ev->event == event) {
-        if(u_prev){
-          u_prev->next = u_ev->next;
-        }
-        tmp = u_ev;
-        u_ev = u_ev->next;
-        cl_free(tmp);
-      }else{
-        if(!u_prev){
-          enqueue_cb->wait_user_events = u_ev;
-        }
-        u_prev=u_ev;
-        u_ev = u_ev->next;
-      }
-    }
-
-    if(!u_prev){
-      enqueue_cb->wait_user_events = NULL;
-    }
+    cl_event_remove_user_event(&enqueue_cb->wait_user_events, event);
 
     /* Still wait on other user events */
     if(enqueue_cb->wait_user_events != NULL) {
@@ -458,6 +440,7 @@ void cl_event_set_status(cl_event event, cl_int status)
 
     //remove user event frome enqueue_cb's ctx
     cl_command_queue_remove_event(enqueue_cb->event->queue, event);
+    cl_command_queue_remove_barrier_event(enqueue_cb->event->queue, event);
 
     /* All user events complete, now wait enqueue events */
     ret = cl_event_wait_events(enqueue_cb->num_events, enqueue_cb->wait_list,
@@ -492,29 +475,19 @@ cl_int cl_event_marker_with_wait_list(cl_command_queue queue,
                 const cl_event *event_wait_list,
                 cl_event* event)
 {
-  enqueue_data data;
-  cl_uint i = 0;
+  enqueue_data data = { 0 };
 
   *event = cl_event_new(queue->ctx, queue, CL_COMMAND_MARKER, CL_TRUE);
   if(event == NULL)
     return CL_OUT_OF_HOST_MEMORY;
 
-  //insert the input events to queue
-  for(i=0; i<num_events_in_wait_list; i++) {
-    if(event_wait_list[i]->type==CL_COMMAND_USER) {
-      cl_command_queue_insert_event(queue, event_wait_list[i]);
-    }else if(event_wait_list[i]->enqueue_cb != NULL) {
-      user_event* user_events = event_wait_list[i]->enqueue_cb->wait_user_events;
-
-      while(user_events != NULL) {
-        cl_command_queue_insert_event(queue, user_events->event);
-        user_events = user_events->next;
-      }
-    }
-  }
-
-  //if wait_events_num>0, the marker event need wait queue->wait_events
-  if(queue->wait_events_num > 0) {
+//enqueues a marker command which waits for either a list of events to complete, or if the list is
+//empty it waits for all commands previously enqueued in command_queue to complete before it  completes.
+  if(num_events_in_wait_list > 0){
+    data.type = EnqueueMarker;
+    cl_event_new_enqueue_callback(*event, &data, num_events_in_wait_list, event_wait_list);
+    return CL_SUCCESS;
+  } else if(queue->wait_events_num > 0) {
     data.type = EnqueueMarker;
     cl_event_new_enqueue_callback(*event, &data, queue->wait_events_num, queue->wait_events);
     return CL_SUCCESS;
@@ -528,6 +501,41 @@ cl_int cl_event_marker_with_wait_list(cl_command_queue queue,
   return CL_SUCCESS;
 }
 
+cl_int cl_event_barrier_with_wait_list(cl_command_queue queue,
+                cl_uint num_events_in_wait_list,
+                const cl_event *event_wait_list,
+                cl_event* event)
+{
+  enqueue_data data = { 0 };
+  cl_event e;
+
+  e = cl_event_new(queue->ctx, queue, CL_COMMAND_BARRIER, CL_TRUE);
+  if(e == NULL)
+    return CL_OUT_OF_HOST_MEMORY;
+
+  if(event != NULL ){
+    *event = e;
+  }
+//enqueues a barrier command which waits for either a list of events to complete, or if the list is
+//empty it waits for all commands previously enqueued in command_queue to complete before it  completes.
+  if(num_events_in_wait_list > 0){
+    data.type = EnqueueBarrier;
+    cl_event_new_enqueue_callback(e, &data, num_events_in_wait_list, event_wait_list);
+    return CL_SUCCESS;
+  } else if(queue->wait_events_num > 0) {
+    data.type = EnqueueBarrier;
+    cl_event_new_enqueue_callback(e, &data, queue->wait_events_num, queue->wait_events);
+    return CL_SUCCESS;
+  }
+
+  if(queue->last_event && queue->last_event->gpgpu_event) {
+    cl_gpgpu_event_update_status(queue->last_event->gpgpu_event, 1);
+  }
+
+  cl_event_set_status(e, CL_COMPLETE);
+  return CL_SUCCESS;
+}
+
 cl_int cl_event_get_timestamp(cl_event event, cl_profiling_info param_name)
 {
   cl_ulong ret_val = 0;
@@ -555,3 +563,48 @@ cl_int cl_event_get_timestamp(cl_event event, cl_profiling_info param_name)
   }
   return CL_INVALID_VALUE;
 }
+
+cl_int cl_event_insert_user_event(user_event** p_u_ev, cl_event event)
+{
+  user_event * u_iter = *p_u_ev;
+  user_event * u_ev;
+
+  while(u_iter)
+  {
+    if(u_iter->event == event)
+      return CL_SUCCESS;
+    u_iter = u_iter->next;
+  }
+
+  TRY_ALLOC_NO_ERR (u_ev, CALLOC(user_event));
+  u_ev->event = event;
+  u_ev->next = *p_u_ev;
+  *p_u_ev = u_ev;
+
+
+  return CL_SUCCESS;
+error:
+  return CL_FALSE;
+}
+
+cl_int cl_event_remove_user_event(user_event** p_u_ev, cl_event event)
+{
+  user_event * u_iter = *p_u_ev;
+  user_event * u_prev = *p_u_ev;
+
+  while(u_iter){
+    if(u_iter->event == event ){
+      if(u_iter == *p_u_ev){
+        *p_u_ev = u_iter->next;
+      }else{
+        u_prev->next = u_iter->next;
+      }
+      cl_free(u_iter);
+      break;
+    }
+    u_prev = u_iter;
+    u_iter = u_iter->next;
+  }
+
+  return CL_SUCCESS;
+}
diff --git a/src/cl_event.h b/src/cl_event.h
index 5a78a8d..bd8a5c7 100644
--- a/src/cl_event.h
+++ b/src/cl_event.h
@@ -91,7 +91,13 @@ void cl_event_set_status(cl_event, cl_int);
 void cl_event_update_status(cl_event);
 /* Create the marker event */
 cl_int cl_event_marker_with_wait_list(cl_command_queue, cl_uint, const cl_event *,  cl_event*);
+/* Create the barrier event */
+cl_int cl_event_barrier_with_wait_list(cl_command_queue, cl_uint, const cl_event *,  cl_event*);
 /* Do the event profiling */
 cl_int cl_event_get_timestamp(cl_event event, cl_profiling_info param_name);
+/*insert the user event*/
+cl_int cl_event_insert_user_event(user_event** p_u_ev, cl_event event);
+/*remove the user event*/
+cl_int cl_event_remove_user_event(user_event** p_u_ev, cl_event event);
 #endif /* __CL_EVENT_H__ */
 
-- 
1.8.1.2



More information about the Beignet mailing list