/** * Set kernel arguments and enqueue it for execution on a device. * * Internally this function sets kernel arguments by calling * ::ccl_kernel_set_args_v(), and enqueues the kernel for execution * by calling ::ccl_kernel_enqueue_ndrange(). * * The ::ccl_kernel_set_args_and_enqueue_ndrange() function performs the * same operation but accepts a `NULL`-terminated variable list of * arguments instead. * * If the ::ccl_arg_skip constant is passed in place of a specific * argument, that argument will not be set by this function call. Any * previously set argument continues to be valid. * * @public @memberof ccl_kernel * * @warning This function is not thread-safe. For multi-threaded * access to the same kernel function, create multiple instances of * a kernel wrapper for the given kernel function with ccl_kernel_new(), * one for each thread. * * @param[in] krnl A kernel wrapper object. * @param[in] cq A command queue wrapper object. * @param[in] work_dim The number of dimensions used to specify the * global work-items and work-items in the work-group. * @param[in] global_work_offset Can be used to specify an array of * `work_dim` unsigned values that describe the offset used to calculate * the global ID of a work-item. * @param[in] global_work_size An array of `work_dim` unsigned values * that describe the number of global work-items in `work_dim` * dimensions that will execute the kernel function. * @param[in] local_work_size An array of `work_dim` unsigned values * that describe the number of work-items that make up a work-group that * will execute the specified kernel. * @param[in,out] evt_wait_lst List of events that need to complete * before this command can be executed. The list will be cleared and * can be reused by client code. * @param[in] args A `NULL`-terminated list of arguments to set. * Arguments must be of type ::CCLArg*, ::CCLBuffer*, ::CCLImage* or * ::CCLSampler*. * @param[out] err Return location for a ::CCLErr object, or `NULL` if error * reporting is to be ignored. * @return Event wrapper object that identifies this command. * */ CCL_EXPORT CCLEvent* ccl_kernel_set_args_and_enqueue_ndrange_v(CCLKernel* krnl, CCLQueue* cq, cl_uint work_dim, const size_t* global_work_offset, const size_t* global_work_size, const size_t* local_work_size, CCLEventWaitList* evt_wait_lst, void** args, CCLErr** err) { /* Make sure krnl is not NULL. */ g_return_val_if_fail(krnl != NULL, NULL); /* Make sure cq is not NULL. */ g_return_val_if_fail(cq != NULL, NULL); /* Make sure err is NULL or it is not set. */ g_return_val_if_fail(err == NULL || *err == NULL, NULL); CCLErr* err_internal = NULL; CCLEvent* evt = NULL; /* Set kernel arguments. */ ccl_kernel_set_args_v(krnl, args); /* Enqueue kernel. */ evt = ccl_kernel_enqueue_ndrange(krnl, cq, work_dim, global_work_offset, global_work_size, local_work_size, evt_wait_lst, &err_internal); ccl_if_err_propagate_goto(err, err_internal, error_handler); /* If we got here, everything is OK. */ g_assert(err == NULL || *err == NULL); goto finish; error_handler: /* If we got here there was an error, verify that it is so. */ g_assert(err == NULL || *err != NULL); finish: /* Return event wrapper. */ return evt; }
/** * @internal * Perform sort using device data. * */ static CCLEvent* clo_sort_gselect_sort_with_device_data( CloSort* sorter, CCLQueue* cq_exec, CCLQueue* cq_comm, CCLBuffer* data_in, CCLBuffer* data_out, size_t numel, size_t lws_max, GError** err) { /* Make sure err is NULL or it is not set. */ g_return_val_if_fail(err == NULL || *err == NULL, NULL); /* Make sure cq_exec is not NULL. */ g_return_val_if_fail(cq_exec != NULL, NULL); /* Worksizes. */ size_t lws, gws; /* OpenCL object wrappers. */ CCLContext* ctx = NULL; CCLDevice* dev = NULL; CCLKernel* krnl = NULL; CCLEvent* evt = NULL; /* Event wait list. */ CCLEventWaitList ewl = NULL; /* Internal error reporting object. */ GError* err_internal = NULL; /* Flag indicating if sorted data is to be copied back to original * buffer, simulating an in-place sort. */ cl_bool copy_back = CL_FALSE; /* If data transfer queue is NULL, use exec queue for data * transfers. */ if (cq_comm == NULL) cq_comm = cq_exec; /* Get device where sort will occurr. */ dev = ccl_queue_get_device(cq_exec, &err_internal); g_if_err_propagate_goto(err, err_internal, error_handler); /* Get the kernel wrapper. */ krnl = ccl_program_get_kernel(clo_sort_get_program(sorter), "gselect", &err_internal); g_if_err_propagate_goto(err, err_internal, error_handler); /* Determine worksizes. */ gws = numel; lws = lws_max; ccl_kernel_suggest_worksizes( krnl, dev, 1, &gws, NULL, &lws, &err_internal); g_if_err_propagate_goto(err, err_internal, error_handler); /* Check if data_out is set. */ if (data_out == NULL) { /* If not create it and set the copy back flag to TRUE. */ /* Get context. */ ctx = ccl_queue_get_context(cq_comm, &err_internal); g_if_err_propagate_goto(err, err_internal, error_handler); /* Set copy-back flag to true. */ copy_back = CL_TRUE; /* Create output buffer. */ data_out = ccl_buffer_new(ctx, CL_MEM_WRITE_ONLY, numel * clo_sort_get_element_size(sorter), NULL, &err_internal); g_if_err_propagate_goto(err, err_internal, error_handler); } else { /* Set copy back flag to FALSE. */ copy_back = CL_FALSE; } /* Set kernel arguments. */ cl_ulong numel_l = numel; ccl_kernel_set_args( krnl, data_in, data_out, ccl_arg_priv(numel_l, cl_ulong), NULL); /* Perform global memory selection sort. */ evt = ccl_kernel_enqueue_ndrange( krnl, cq_exec, 1, NULL, &gws, &lws, NULL, &err_internal); g_if_err_propagate_goto(err, err_internal, error_handler); ccl_event_set_name(evt, "gselect_ndrange"); /* If copy-back flag is set, copy sorted data back to original * buffer. */ if (copy_back) { ccl_event_wait_list_add(&ewl, evt, NULL); evt = ccl_buffer_enqueue_copy(data_out, data_in, cq_comm, 0, 0, numel * clo_sort_get_element_size(sorter), &ewl, &err_internal); g_if_err_propagate_goto(err, err_internal, error_handler); ccl_event_set_name(evt, "gselect_copy"); } /* If we got here, everything is OK. */ g_assert(err == NULL || *err == NULL); goto finish; error_handler: /* If we got here there was an error, verify that it is so. */ g_assert(err == NULL || *err != NULL); evt = NULL; finish: /* Free data out buffer if copy-back flag is set. */ if ((copy_back) && (data_out != NULL)) ccl_buffer_destroy(data_out); /* Return event wait list. */ return evt; }