[Beignet] [PATCH 2/2] add [opencl-1.2] API clEnqueueBarrierWithWaitList.
xionghu.luo at intel.com
xionghu.luo at intel.com
Sun May 4 15:08:46 PDT 2014
From: Luo <xionghu.luo at intel.com>
API clEnqueueMarkerWithWaitList patch didn't push the latest, update in
this patch;
the difference between clEnqueueMarkerWithWaitList and this API is
that this API would block later enqueued calls, so added a barrier_events
queue to manager barrier's wait list.
Signed-off-by: Luo <xionghu.luo at intel.com>
---
src/cl_api.c | 22 +++++++-
src/cl_command_queue.c | 66 +++++++++++++++++++++--
src/cl_command_queue.h | 9 ++--
src/cl_enqueue.h | 1 +
src/cl_event.c | 144 +++++++++++++++++++++++++++++++++++++------------
src/cl_event.h | 6 +++
6 files changed, 206 insertions(+), 42 deletions(-)
diff --git a/src/cl_api.c b/src/cl_api.c
index 9c22819..8902665 100644
--- a/src/cl_api.c
+++ b/src/cl_api.c
@@ -2753,8 +2753,28 @@ 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);
+ if(event == NULL) {
+ err = CL_INVALID_VALUE;
+ goto error;
+ }
+ 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..0b22485 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..079c98d 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;
}
}
@@ -458,6 +463,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 +498,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 +524,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 +586,50 @@ 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;
+ }
+ cl_free(u_iter);
+ break;
+ }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