/* * Copyright 2017 Google Inc. * * Use of this source code is governed by a BSD-style license that can * be found in the LICENSE file. * */ // // squelch OpenCL 1.2 deprecation warning // #ifndef CL_USE_DEPRECATED_OPENCL_1_2_APIS #define CL_USE_DEPRECATED_OPENCL_1_2_APIS #endif // // // #include #include // // // #include "runtime_cl_12.h" #include "common/cl/assert_cl.h" // // This implementation is probably excessive. // // The command queue pool could easily be replaced with simply an LRU // or even round-robin reuse pool. Even a small number of aliased // command queues can probably enough concurrency. // #define SKC_CQ_POOL_EXPAND 1 // // // static cl_command_queue skc_runtime_cl_12_create_cq(struct skc_runtime * const runtime, struct skc_cq_pool * const pool) { cl_command_queue cq; #if 1 // // <= OpenCL 1.2 // cl_int cl_err; cq = clCreateCommandQueue(runtime->cl.context, runtime->cl.device_id, pool->cq_props, &cl_err); cl_ok(cl_err); #else if (runtime_cl->version.major < 2) { // // <= OpenCL 1.2 // cl_int cl_err; cq = clCreateCommandQueue(runtime_cl->context, runtime_cl->device_id, (cl_command_queue_properties)type, &cl_err); cl_ok(cl_err); } else { // // >= OpenCL 2.0 // cl_int cl_err; cl_queue_properties const queue_properties[] = { CL_QUEUE_PROPERTIES,(cl_queue_properties)type,0 }; cq = clCreateCommandQueueWithProperties(runtime_cl->context, runtime_cl->device_id, queue_properties, &cl_err); cl_ok(cl_err); } #endif return cq; } // // // void skc_cq_pool_create(struct skc_runtime * const runtime, struct skc_cq_pool * const pool, cl_command_queue_properties const cq_props, skc_uint const size) { pool->size = size + 1; // an empty spot pool->reads = 0; pool->writes = size; pool->cq_props = cq_props; pool->cq = skc_runtime_host_perm_alloc(runtime,SKC_MEM_FLAGS_READ_WRITE, pool->size * sizeof(*pool->cq)); for (skc_uint ii=0; iicq[ii] = skc_runtime_cl_12_create_cq(runtime,pool); pool->cq[size] = NULL; } // // // void skc_cq_pool_dispose(struct skc_runtime * const runtime, struct skc_cq_pool * pool) { // // FIXME -- release the command queues after waiting for the ring to // be full with pool.size queues? // skc_runtime_host_perm_free(runtime,pool->cq); } // // // static void skc_cq_pool_write(struct skc_cq_pool * const pool, cl_command_queue cq) { pool->cq[pool->writes++ % pool->size] = cq; } // // only expand when completely empty // static void skc_cq_pool_expand(struct skc_runtime * const runtime, struct skc_cq_pool * const pool, skc_uint expand) { #ifndef NDEBUG fprintf(stderr,"Expanding the cq_pool by: %u (%u)\n",expand,pool->size); #endif // free old skc_runtime_host_perm_free(runtime,pool->cq); // the ring is empty pool->size += expand; pool->cq = skc_runtime_host_perm_alloc(runtime,SKC_MEM_FLAGS_READ_WRITE,pool->size * sizeof(*pool->cq)); pool->reads = 0; pool->writes = expand; for (skc_uint ii=0; iicq[ii] = skc_runtime_cl_12_create_cq(runtime,pool); } // // // static cl_command_queue skc_cq_pool_read(struct skc_runtime * const runtime, struct skc_cq_pool * const pool) { // any command queues left? if (pool->reads == pool->writes) skc_cq_pool_expand(runtime,pool,SKC_CQ_POOL_EXPAND); cl_command_queue cq = pool->cq[pool->reads++ % pool->size]; return cq; } // // // cl_command_queue skc_runtime_acquire_cq_in_order(struct skc_runtime * const runtime) { return skc_cq_pool_read(runtime,&runtime->cq_pool); } void skc_runtime_release_cq_in_order(struct skc_runtime * const runtime, cl_command_queue cq) { skc_cq_pool_write(&runtime->cq_pool,cq); } // // //