Home | History | Annotate | Download | only in cl_12
      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