1 /* 2 * Copyright 2017 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can 5 * be found in the LICENSE file. 6 * 7 */ 8 9 // 10 // squelch OpenCL 1.2 deprecation warning 11 // 12 13 #ifndef CL_USE_DEPRECATED_OPENCL_1_2_APIS 14 #define CL_USE_DEPRECATED_OPENCL_1_2_APIS 15 #endif 16 17 // 18 // 19 // 20 21 #include <stdio.h> 22 #include <string.h> 23 24 // 25 // 26 // 27 28 #include "runtime_cl_12.h" 29 #include "common/cl/assert_cl.h" 30 31 // 32 // This implementation is probably excessive. 33 // 34 // The command queue pool could easily be replaced with simply an LRU 35 // or even round-robin reuse pool. Even a small number of aliased 36 // command queues can probably enough concurrency. 37 // 38 39 #define SKC_CQ_POOL_EXPAND 1 40 41 // 42 // 43 // 44 45 static 46 cl_command_queue 47 skc_runtime_cl_12_create_cq(struct skc_runtime * const runtime, 48 struct skc_cq_pool * const pool) 49 50 { 51 cl_command_queue cq; 52 53 #if 1 54 // 55 // <= OpenCL 1.2 56 // 57 cl_int cl_err; 58 59 cq = clCreateCommandQueue(runtime->cl.context, 60 runtime->cl.device_id, 61 pool->cq_props, 62 &cl_err); cl_ok(cl_err); 63 #else 64 if (runtime_cl->version.major < 2) 65 { 66 // 67 // <= OpenCL 1.2 68 // 69 cl_int cl_err; 70 71 cq = clCreateCommandQueue(runtime_cl->context, 72 runtime_cl->device_id, 73 (cl_command_queue_properties)type, 74 &cl_err); cl_ok(cl_err); 75 } 76 else 77 { 78 // 79 // >= OpenCL 2.0 80 // 81 cl_int cl_err; 82 cl_queue_properties const queue_properties[] = { 83 CL_QUEUE_PROPERTIES,(cl_queue_properties)type,0 84 }; 85 86 cq = clCreateCommandQueueWithProperties(runtime_cl->context, 87 runtime_cl->device_id, 88 queue_properties, 89 &cl_err); cl_ok(cl_err); 90 } 91 #endif 92 93 return cq; 94 } 95 96 // 97 // 98 // 99 100 void 101 skc_cq_pool_create(struct skc_runtime * const runtime, 102 struct skc_cq_pool * const pool, 103 cl_command_queue_properties const cq_props, 104 skc_uint const size) 105 { 106 pool->size = size + 1; // an empty spot 107 pool->reads = 0; 108 pool->writes = size; 109 110 pool->cq_props = cq_props; 111 pool->cq = skc_runtime_host_perm_alloc(runtime,SKC_MEM_FLAGS_READ_WRITE, 112 pool->size * sizeof(*pool->cq)); 113 for (skc_uint ii=0; ii<size; ii++) 114 pool->cq[ii] = skc_runtime_cl_12_create_cq(runtime,pool); 115 116 pool->cq[size] = NULL; 117 } 118 119 // 120 // 121 // 122 123 void 124 skc_cq_pool_dispose(struct skc_runtime * const runtime, 125 struct skc_cq_pool * pool) 126 { 127 // 128 // FIXME -- release the command queues after waiting for the ring to 129 // be full with pool.size queues? 130 // 131 skc_runtime_host_perm_free(runtime,pool->cq); 132 } 133 134 // 135 // 136 // 137 138 static 139 void 140 skc_cq_pool_write(struct skc_cq_pool * const pool, 141 cl_command_queue cq) 142 { 143 pool->cq[pool->writes++ % pool->size] = cq; 144 } 145 146 // 147 // only expand when completely empty 148 // 149 150 static 151 void 152 skc_cq_pool_expand(struct skc_runtime * const runtime, 153 struct skc_cq_pool * const pool, 154 skc_uint expand) 155 { 156 #ifndef NDEBUG 157 fprintf(stderr,"Expanding the cq_pool by: %u (%u)\n",expand,pool->size); 158 #endif 159 160 // free old 161 skc_runtime_host_perm_free(runtime,pool->cq); 162 163 // the ring is empty 164 pool->size += expand; 165 pool->cq = skc_runtime_host_perm_alloc(runtime,SKC_MEM_FLAGS_READ_WRITE,pool->size * sizeof(*pool->cq)); 166 pool->reads = 0; 167 pool->writes = expand; 168 169 for (skc_uint ii=0; ii<expand; ii++) 170 pool->cq[ii] = skc_runtime_cl_12_create_cq(runtime,pool); 171 } 172 173 // 174 // 175 // 176 177 static 178 cl_command_queue 179 skc_cq_pool_read(struct skc_runtime * const runtime, 180 struct skc_cq_pool * const pool) 181 { 182 // any command queues left? 183 if (pool->reads == pool->writes) 184 skc_cq_pool_expand(runtime,pool,SKC_CQ_POOL_EXPAND); 185 186 cl_command_queue cq = pool->cq[pool->reads++ % pool->size]; 187 188 return cq; 189 } 190 191 // 192 // 193 // 194 195 cl_command_queue 196 skc_runtime_acquire_cq_in_order(struct skc_runtime * const runtime) 197 { 198 return skc_cq_pool_read(runtime,&runtime->cq_pool); 199 } 200 201 void 202 skc_runtime_release_cq_in_order(struct skc_runtime * const runtime, 203 cl_command_queue cq) 204 { 205 skc_cq_pool_write(&runtime->cq_pool,cq); 206 } 207 208 // 209 // 210 // 211