[Beignet] [Patch V2 3/3] OCL20: add svm enqueue apis and svm's sub buffer support.
Song, Ruiling
ruiling.song at intel.com
Mon Nov 16 23:15:13 PST 2015
The patchset LGTM.
Thanks!
Ruilng
> -----Original Message-----
> From: Beignet [mailto:beignet-bounces at lists.freedesktop.org] On Behalf Of
> Yang Rong
> Sent: Tuesday, November 10, 2015 3:52 PM
> To: beignet at lists.freedesktop.org
> Cc: Yang, Rong R <rong.r.yang at intel.com>
> Subject: [Beignet] [Patch V2 3/3] OCL20: add svm enqueue apis and svm's
> sub buffer support.
>
> Signed-off-by: Yang Rong <rong.r.yang at intel.com>
> ---
> src/cl_api.c | 154
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> src/cl_context.c | 5 +-
> src/cl_context.h | 2 +-
> src/cl_enqueue.c | 65 +++++++++++++++++++++++
> src/cl_enqueue.h | 9 ++++
> src/cl_khr_icd.c | 6 +--
> 6 files changed, 235 insertions(+), 6 deletions(-)
>
> diff --git a/src/cl_api.c b/src/cl_api.c
> index 134870d..c5cb67a 100644
> --- a/src/cl_api.c
> +++ b/src/cl_api.c
> @@ -599,6 +599,63 @@ error:
> }
>
> cl_int
> +clEnqueueSVMFree (cl_command_queue command_queue,
> + cl_uint num_svm_pointers,
> + void *svm_pointers[],
> + void (CL_CALLBACK *pfn_free_func)( cl_command_queue queue,
> + cl_uint num_svm_pointers,
> + void *svm_pointers[],
> + void *user_data),
> + void *user_data,
> + cl_uint num_events_in_wait_list,
> + const cl_event *event_wait_list,
> + cl_event *event)
> +{
> + cl_int err = CL_SUCCESS;
> + cl_int i = 0;
> + void** pointers = NULL;
> + enqueue_data *data, defer_enqueue_data = { 0 };
> + CHECK_QUEUE(command_queue);
> +
> + if(num_svm_pointers == 0 || svm_pointers == NULL) {
> + err = CL_INVALID_VALUE;
> + goto error;
> + }
> + for(i=0; i<num_svm_pointers; i++) {
> + if(svm_pointers[i] == NULL) {
> + err = CL_INVALID_VALUE;
> + goto error;
> + }
> + }
> +
> + TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list,
> event, command_queue->ctx);
> +
> + pointers = malloc(num_svm_pointers * sizeof(void *));
> + if(UNLIKELY(pointers == NULL)) {
> + err = CL_OUT_OF_HOST_MEMORY;
> + goto error;
> + }
> + memcpy(pointers, svm_pointers, num_svm_pointers * sizeof(void *));
> +
> + data = &defer_enqueue_data;
> + data->type = EnqueueSVMFree;
> + data->queue = command_queue;
> + data->pointers = pointers;
> + data->free_func = pfn_free_func;
> + data->size = num_svm_pointers;
> + data->ptr = user_data;
> +
> + if(handle_events(command_queue, num_events_in_wait_list,
> event_wait_list,
> + event, data, CL_COMMAND_SVM_FREE) ==
> CL_ENQUEUE_EXECUTE_IMM) {
> + err = cl_enqueue_handle(event ? *event : NULL, data);
> + if(event) cl_event_set_status(*event, CL_COMPLETE);
> + }
> +
> +error:
> + return err;
> +}
> +
> +cl_int
> clEnqueueSVMMap (cl_command_queue command_queue,
> cl_bool blocking_map,
> cl_map_flags map_flags,
> @@ -620,6 +677,8 @@ clEnqueueSVMMap (cl_command_queue
> command_queue,
>
> clEnqueueMapBuffer(command_queue, buffer, blocking_map, map_flags,
> 0, size,
> num_events_in_wait_list, event_wait_list, event, &err);
> + if(event)
> + (*event)->type = CL_COMMAND_SVM_MAP;
> error:
> return err;
> }
> @@ -643,11 +702,106 @@ clEnqueueSVMUnmap (cl_command_queue
> command_queue,
>
> err = clEnqueueUnmapMemObject(command_queue, buffer, svm_ptr,
> num_events_in_wait_list, event_wait_list, event);
> + if(event)
> + (*event)->type = CL_COMMAND_SVM_UNMAP;
> +
> +error:
> + return err;
> +}
> +
> +cl_int clEnqueueSVMMemcpy (cl_command_queue command_queue,
> + cl_bool blocking_copy,
> + void *dst_ptr,
> + const void *src_ptr,
> + size_t size,
> + cl_uint num_events_in_wait_list,
> + const cl_event *event_wait_list,
> + cl_event *event)
> +{
> + cl_int err = CL_SUCCESS;
> + enqueue_data *data, defer_enqueue_data = { 0 };
> +
> + if(UNLIKELY(dst_ptr == NULL || src_ptr == NULL || size == 0 )) {
> + err = CL_INVALID_VALUE;
> + goto error;
> + }
> +
> + if(((size_t)src_ptr < (size_t)dst_ptr && ((size_t)src_ptr + size >
> (size_t)dst_ptr)) ||
> + ((size_t)dst_ptr < (size_t)src_ptr && ((size_t)dst_ptr + size >
> (size_t)src_ptr))) {
> + err = CL_MEM_COPY_OVERLAP;
> + goto error;
> + }
> +
> + TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list,
> event, command_queue->ctx);
> +
> + data = &defer_enqueue_data;
> + data->type = EnqueueSVMMemCopy;
> + data->queue = command_queue;
> + data->ptr = dst_ptr;
> + data->const_ptr = src_ptr;
> + data->size = size;
> +
> + if(handle_events(command_queue, num_events_in_wait_list,
> event_wait_list,
> + event, data, CL_COMMAND_SVM_MEMCPY) ==
> CL_ENQUEUE_EXECUTE_IMM) {
> + err = cl_enqueue_handle(event ? *event : NULL, data);
> + if(event) cl_event_set_status(*event, CL_COMPLETE);
> + }
>
> error:
> return err;
> }
>
> +cl_int clEnqueueSVMMemFill (cl_command_queue command_queue,
> + void *svm_ptr,
> + const void *pattern,
> + size_t pattern_size,
> + size_t size,
> + cl_uint num_events_in_wait_list,
> + const cl_event *event_wait_list,
> + cl_event *event)
> +{
> + cl_int err = CL_SUCCESS;
> + enqueue_data *data, defer_enqueue_data = { 0 };
> +
> + CHECK_QUEUE(command_queue);
> + if(UNLIKELY(svm_ptr == NULL ||
> + ((size_t)svm_ptr & (pattern_size - 1)) != 0)) {
> + err = CL_INVALID_VALUE;
> + goto error;
> + }
> +
> + if(UNLIKELY(pattern == NULL ||
> + (pattern_size & (pattern_size - 1)) != 0 ||
> + pattern_size > 128)) {
> + err = CL_INVALID_VALUE;
> + goto error;
> + }
> +
> + if(UNLIKELY(size == 0 ||
> + (size % pattern_size) != 0)) {
> + err = CL_INVALID_VALUE;
> + goto error;
> + }
> +
> + TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list,
> event, command_queue->ctx);
> +
> + data = &defer_enqueue_data;
> + data->type = EnqueueSVMMemFill;
> + data->queue = command_queue;
> + data->ptr = svm_ptr;
> + data->const_ptr = pattern;
> + data->pattern_size = pattern_size;
> + data->size = size;
> +
> + if(handle_events(command_queue, num_events_in_wait_list,
> event_wait_list,
> + event, data, CL_COMMAND_SVM_MEMFILL) ==
> CL_ENQUEUE_EXECUTE_IMM) {
> + err = cl_enqueue_handle(event ? *event : NULL, data);
> + if(event) cl_event_set_status(*event, CL_COMPLETE);
> + }
> +
> +error:
> + return err;
> +}
>
> cl_mem
> clCreateImage2D(cl_context context,
> diff --git a/src/cl_context.c b/src/cl_context.c
> index 3fcdb63..6bdf272 100644
> --- a/src/cl_context.c
> +++ b/src/cl_context.c
> @@ -330,12 +330,13 @@ unlock:
> }
>
> cl_mem
> -cl_context_get_svm_from_ptr(cl_context ctx, void * p)
> +cl_context_get_svm_from_ptr(cl_context ctx, const void * p)
> {
> cl_mem buf = ctx->svm_buffers;
> while(buf) {
> assert(buf->host_ptr && buf->is_svm);
> - if(buf->host_ptr == p)
> + if((size_t)buf->host_ptr <= (size_t)p &&
> + (size_t)p < ((size_t)buf->host_ptr + buf->size))
> return buf;
> buf = buf->next;
> }
> diff --git a/src/cl_context.h b/src/cl_context.h
> index 365ec32..8c462b1 100644
> --- a/src/cl_context.h
> +++ b/src/cl_context.h
> @@ -171,6 +171,6 @@ extern cl_kernel
> cl_context_get_static_kernel_from_bin(cl_context ctx, cl_int in
> const char * str_kernel, size_t size, const char * str_option);
>
> /* Get the SVM from pointer, return NULL if pointer is not from SVM */
> -extern cl_mem cl_context_get_svm_from_ptr(cl_context ctx, void *p);
> +extern cl_mem cl_context_get_svm_from_ptr(cl_context ctx, const void
> *p);
> #endif /* __CL_CONTEXT_H__ */
>
> diff --git a/src/cl_enqueue.c b/src/cl_enqueue.c
> index 371b2d4..4fea6f9 100644
> --- a/src/cl_enqueue.c
> +++ b/src/cl_enqueue.c
> @@ -443,6 +443,65 @@ error:
> return err;
> }
>
> +cl_int cl_enqueue_svm_free(enqueue_data *data) {
> + int i;
> + void **pointers = data->pointers;
> + uint num_svm_ptrs = data->size;
> +
> + if(data->free_func) {
> + data->free_func(data->queue, num_svm_ptrs, pointers, data->ptr);
> + } else {
> + for(i=0; i<num_svm_ptrs; i++)
> + cl_mem_svm_delete(data->queue->ctx, pointers[i]);
> + }
> +
> + free(pointers);
> + return CL_SUCCESS;
> +}
> +
> +cl_int cl_enqueue_svm_mem_copy(enqueue_data *data) {
> + cl_mem mem;
> + size_t size = data->size;
> + const char* src_ptr = (const char *)data->const_ptr;
> + char *dst_ptr = (char *)data->ptr;
> + int i;
> +
> + if((mem = cl_context_get_svm_from_ptr(data->queue->ctx, data-
> >ptr)) != NULL) {
> + dst_ptr = (char *)cl_mem_map_auto(mem, 1);
> + }
> +
> + if((mem = cl_context_get_svm_from_ptr(data->queue->ctx, data-
> >const_ptr)) != NULL) {
> + src_ptr = (const char *)cl_mem_map_auto(mem, 0);
> + }
> +
> + for(i=0; i<size; i++) {
> + dst_ptr[i] = src_ptr[i];
> + }
> +
> + return CL_SUCCESS;
> +}
> +
> +cl_int cl_enqueue_svm_mem_fill(enqueue_data *data) {
> + cl_mem mem;
> + size_t size = data->size;
> + size_t pattern_size = data->pattern_size;
> + const char* pattern = (const char *)data->const_ptr;
> + char *ptr = (char *)data->ptr;
> + int i, j;
> +
> + if((mem = cl_context_get_svm_from_ptr(data->queue->ctx, data-
> >ptr)) != NULL) {
> + ptr = (char *)cl_mem_map_auto(mem, 1);
> + }
> +
> + for(i=0; i<size; ) {
> + for(j=0; j<pattern_size; j++) {
> + ptr[i++] = pattern[j];
> + }
> + }
> +
> + return CL_SUCCESS;
> +}
> +
> cl_int cl_enqueue_handle(cl_event event, enqueue_data* data)
> {
> /* if need profiling, add the submit timestamp here. */
> @@ -481,6 +540,12 @@ cl_int cl_enqueue_handle(cl_event event,
> enqueue_data* data)
> return cl_event_flush(event);
> case EnqueueNativeKernel:
> return cl_enqueue_native_kernel(data);
> + case EnqueueSVMFree:
> + return cl_enqueue_svm_free(data);
> + case EnqueueSVMMemCopy:
> + return cl_enqueue_svm_mem_copy(data);
> + case EnqueueSVMMemFill:
> + return cl_enqueue_svm_mem_fill(data);
> case EnqueueMigrateMemObj:
> default:
> return CL_SUCCESS;
> diff --git a/src/cl_enqueue.h b/src/cl_enqueue.h
> index 09305af..faa85d2 100644
> --- a/src/cl_enqueue.h
> +++ b/src/cl_enqueue.h
> @@ -45,6 +45,9 @@ typedef enum {
> EnqueueFillBuffer,
> EnqueueFillImage,
> EnqueueMigrateMemObj,
> + EnqueueSVMFree,
> + EnqueueSVMMemCopy,
> + EnqueueSVMMemFill,
> EnqueueInvalid
> } enqueue_type;
>
> @@ -66,7 +69,13 @@ typedef struct _enqueue_data {
> const cl_mem* mem_list; /* mem_list of clEnqueueNativeKernel */
> uint8_t unsync_map; /* Indicate the clEnqueueMapBuffer/Image is
> unsync map */
> uint8_t write_map; /* Indicate if the clEnqueueMapBuffer is write
> enable */
> + void ** pointers; /* The svm_pointers of clEnqueueSVMFree */
> + size_t pattern_size; /* the pattern_size of clEnqueueSVMMemFill
> */
> void (*user_func)(void *); /* pointer to a host-callable user function */
> + void (CL_CALLBACK *free_func)( cl_command_queue queue,
> + cl_uint num_svm_pointers,
> + void *svm_pointers[],
> + void *user_data); /* pointer to pfn_free_func of
> clEnqueueSVMFree */
> } enqueue_data;
>
> /* Do real enqueue commands */
> diff --git a/src/cl_khr_icd.c b/src/cl_khr_icd.c
> index 0894d61..73d1924 100644
> --- a/src/cl_khr_icd.c
> +++ b/src/cl_khr_icd.c
> @@ -177,9 +177,9 @@ struct _cl_icd_dispatch const cl_khr_icd_dispatch = {
> (void *) NULL /* clGetPipeInfo */,
> clSVMAlloc,
> clSVMFree,
> - (void *) NULL /* clEnqueueSVMFree */,
> - (void *) NULL /* clEnqueueSVMMemcpy */,
> - (void *) NULL /* clEnqueueSVMMemFill */,
> + (void *) clEnqueueSVMFree,
> + (void *) clEnqueueSVMMemcpy,
> + (void *) clEnqueueSVMMemFill,
> (void *) clEnqueueSVMMap,
> (void *) clEnqueueSVMUnmap,
> (void *) NULL /* clCreateSamplerWithProperties */,
> --
> 2.1.4
>
> _______________________________________________
> Beignet mailing list
> Beignet at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/beignet
More information about the Beignet
mailing list