• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
skc_runtime_cl_12_create_cq(struct skc_runtime * const runtime,struct skc_cq_pool * const pool)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
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)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
skc_cq_pool_dispose(struct skc_runtime * const runtime,struct skc_cq_pool * pool)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
skc_cq_pool_write(struct skc_cq_pool * const pool,cl_command_queue cq)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
skc_cq_pool_expand(struct skc_runtime * const runtime,struct skc_cq_pool * const pool,skc_uint expand)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
skc_cq_pool_read(struct skc_runtime * const runtime,struct skc_cq_pool * const pool)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
skc_runtime_acquire_cq_in_order(struct skc_runtime * const runtime)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
skc_runtime_release_cq_in_order(struct skc_runtime * const runtime,cl_command_queue cq)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