/** * @internal * * @brief Tests copy operations from one buffer to another. * */ static void copy_test() { /* Test variables. */ CCLContext * ctx = NULL; CCLDevice * d = NULL; CCLBuffer * b1 = NULL; CCLBuffer * b2 = NULL; CCLQueue * q; cl_long h1[CCL_TEST_BUFFER_SIZE]; cl_long h2[CCL_TEST_BUFFER_SIZE]; size_t buf_size = sizeof(cl_long) * CCL_TEST_BUFFER_SIZE; CCLErr * err = NULL; /* Create a host array, put some stuff in it. */ for (guint i = 0; i < CCL_TEST_BUFFER_SIZE; ++i) h1[i] = g_test_rand_int(); /* Get the test context with the pre-defined device. */ ctx = ccl_test_context_new(&err); g_assert_no_error(err); /* Get first device in context. */ d = ccl_context_get_device(ctx, 0, &err); g_assert_no_error(err); /* Create a command queue. */ q = ccl_queue_new(ctx, d, 0, &err); g_assert_no_error(err); /* Create regular buffer and write data from the host buffer. */ b1 = ccl_buffer_new( ctx, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, buf_size, h1, &err); g_assert_no_error(err); /* Create another buffer, double the size. */ b2 = ccl_buffer_new(ctx, CL_MEM_READ_WRITE, 2 * buf_size, NULL, &err); g_assert_no_error(err); /* Copy data from first buffer to second buffer, using an offset on * the second buffer. */ ccl_buffer_enqueue_copy( b1, b2, q, 0, buf_size / 2, buf_size, NULL, &err); g_assert_no_error(err); /* Read data back to host from the second buffer. */ ccl_buffer_enqueue_read( b2, q, CL_TRUE, buf_size / 2, buf_size, h2, NULL, &err); g_assert_no_error(err); /* Check data is OK. */ for (guint i = 0; i < CCL_TEST_BUFFER_SIZE; ++i) g_assert_cmpuint(h1[i], ==, h2[i]); /* Free stuff. */ ccl_buffer_destroy(b1); ccl_buffer_destroy(b2); ccl_queue_destroy(q); ccl_context_destroy(ctx); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); }
/** * @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; }
/** * Tests creation, getting info from and destruction of * profiler objects, and their relationship with context, device and * queue wrapper objects. * */ static void create_add_destroy_test() { /* Test variables. */ CCLErr* err = NULL; CCLBuffer* buf1 = NULL; CCLBuffer* buf2 = NULL; CCLProf* prof = NULL; CCLContext* ctx = NULL; CCLDevice* d = NULL; CCLQueue* cq1 = NULL; CCLQueue* cq2 = NULL; CCLEvent* evt = NULL; CCLEventWaitList ewl = NULL; size_t buf_size = 8 * sizeof(cl_short); cl_short hbuf[8] = {1, 2, 3, 4, 5, 6, 7, 8}; cl_ulong duration, eff_duration; double time_elapsed; /* Create a new profile object. */ prof = ccl_prof_new(); /* Get a context and a device. */ ctx = ccl_test_context_new(&err); g_assert_no_error(err); d = ccl_context_get_device(ctx, 0, &err); g_assert_no_error(err); /* Create two command queue wrappers. */ cq1 = ccl_queue_new(ctx, d, CL_QUEUE_PROFILING_ENABLE, &err); g_assert_no_error(err); cq2 = ccl_queue_new(ctx, d, CL_QUEUE_PROFILING_ENABLE, &err); g_assert_no_error(err); /* Create device buffers. */ buf1 = ccl_buffer_new(ctx, CL_MEM_READ_ONLY, buf_size, NULL, &err); g_assert_no_error(err); buf2 = ccl_buffer_new(ctx, CL_MEM_READ_WRITE, buf_size, NULL, &err); g_assert_no_error(err); /* Start profile object timer. */ ccl_prof_start(prof); /* Transfer data to buffer. */ evt = ccl_buffer_enqueue_write( buf1, cq1, CL_FALSE, 0, buf_size, hbuf, NULL, &err); g_assert_no_error(err); /* Transfer data from one buffer to another. */ evt = ccl_buffer_enqueue_copy(buf1, buf2, cq2, 0, 0, buf_size, ccl_ewl(&ewl, evt, NULL), &err); g_assert_no_error(err); /* Wait for copy. */ ccl_event_wait(ccl_ewl(&ewl, evt, NULL), &err); g_assert_no_error(err); /* Stop profile object timer. */ ccl_prof_stop(prof); /* Add both queues to profile object. */ ccl_prof_add_queue(prof, "A Queue", cq1); ccl_prof_add_queue(prof, "Another Queue", cq2); /* Process queues. */ ccl_prof_calc(prof, &err); g_assert_no_error(err); /* Request some profiling information. */ time_elapsed = ccl_prof_time_elapsed(prof); duration = ccl_prof_get_duration(prof); eff_duration = ccl_prof_get_eff_duration(prof); g_debug("Profiling time elapsed: %lf", time_elapsed); g_debug("Profiling duration: %d", (cl_int) duration); g_debug("Profiling eff. duration: %d", (cl_int) eff_duration); /* Destroy buffers. */ ccl_buffer_destroy(buf1); ccl_buffer_destroy(buf2); /* Unref cq1, which should not be destroyed because it is held * by the profile object. */ ccl_queue_destroy(cq1); /* Destroy the profile object, which will also destroy cq1. cq2 * will me merely unrefed and must still be explicitly destroyed. */ ccl_prof_destroy(prof); /* Destroy cq2. */ ccl_queue_destroy(cq2); /* Destroy the context. */ ccl_context_destroy(ctx); /* Confirm that memory allocated by wrappers has been properly * freed. */ g_assert(ccl_wrapper_memcheck()); }