ViennaCL - The Vienna Computing Library  1.5.1
viennacl/ocl/backend.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_OCL_BACKEND_HPP_
00002 #define VIENNACL_OCL_BACKEND_HPP_
00003 
00004 /* =========================================================================
00005    Copyright (c) 2010-2014, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008    Portions of this software are copyright by UChicago Argonne, LLC.
00009 
00010                             -----------------
00011                   ViennaCL - The Vienna Computing Library
00012                             -----------------
00013 
00014    Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at
00015 
00016    (A list of authors and contributors can be found in the PDF manual)
00017 
00018    License:         MIT (X11), see file LICENSE in the base directory
00019 ============================================================================= */
00020 
00025 #include <vector>
00026 #include "viennacl/ocl/context.hpp"
00027 #include "viennacl/ocl/enqueue.hpp"
00028 
00029 namespace viennacl
00030 {
00031   namespace ocl
00032   {
00033 
00035     template <bool dummy = false>  //never use parameter other than default (introduced for linkage issues only)
00036     class backend
00037     {
00038       public:
00043         static void switch_context(long i)
00044         {
00045           current_context_id_ = i;
00046         }
00047 
00049         static viennacl::ocl::context & context(long id)
00050         {
00051           if (!initialized_[id])
00052           {
00053             //std::cout << "Initializing context no. " << current_context_id_ << std::endl;
00054             contexts_[id].init();
00055             //create one queue per device:
00056             std::vector<viennacl::ocl::device> devices = contexts_[id].devices();
00057             for (vcl_size_t j = 0; j<devices.size(); ++j)
00058               contexts_[id].add_queue(devices[j]);
00059             initialized_[id] = true;
00060             /*
00061             std::cout << "Context no. " << current_context_id_ << " initialized with " << devices.size() << " devices" << std::endl;
00062             std::cout << "Device id: " << devices[0].id() << std::endl;
00063             std::cout << "Current device id: " << contexts_[current_context_id_].current_device().id() << std::endl; */
00064           }
00065           return contexts_[id];
00066         }
00067 
00069         static viennacl::ocl::context & current_context()
00070         {
00071           return backend<dummy>::context(current_context_id_);
00072         }
00073 
00075         static viennacl::ocl::command_queue & get_queue()
00076         {
00077           return current_context().get_queue();
00078         }
00079 
00085         static void setup_context(long i,
00086                                   std::vector<cl_device_id> const & devices)
00087         {
00088           if (initialized_[i])
00089             std::cerr << "ViennaCL: Warning in init_context(): Providing a list of devices has no effect, because context for ViennaCL is already created!" << std::endl;
00090           else
00091           {
00092             //set devices for context:
00093             for (vcl_size_t j = 0; j<devices.size(); ++j)
00094               contexts_[i].add_device(devices[j]);
00095           }
00096         }
00097 
00105         static void setup_context(long i,
00106                                   cl_context c,
00107                                   std::vector<cl_device_id> const & devices,
00108                                   std::map< cl_device_id, std::vector< cl_command_queue > > const & queues)
00109         {
00110           assert(devices.size() == queues.size() && bool("ViennaCL expects one queue per device!"));
00111 
00112           if (initialized_[i])
00113             std::cerr << "ViennaCL: Warning in init_context(): Providing a list of devices has no effect, because context for ViennaCL is already created!" << std::endl;
00114           else
00115           {
00116             //set devices for context:
00117             for (vcl_size_t j = 0; j<devices.size(); ++j)
00118               contexts_[i].add_device(devices[j]);
00119 
00120             //init context:
00121             contexts_[i].init(c);
00122 
00123             //add queues:
00124             typedef typename std::map< cl_device_id, std::vector< cl_command_queue > >::const_iterator queue_iterator;
00125             for (queue_iterator qit = queues.begin();
00126                                 qit != queues.end();
00127                               ++qit)
00128             {
00129               std::vector<cl_command_queue> const & queues_for_device = qit->second;
00130               for (vcl_size_t j=0; j<queues_for_device.size(); ++j)
00131                 contexts_[i].add_queue(qit->first, queues_for_device[j]);
00132             }
00133 
00134             initialized_[i] = true;
00135           }
00136         }
00137 
00145         static void setup_context(long i, cl_context c, std::vector<cl_device_id> const & devices, std::vector<cl_command_queue> const & queue)
00146         {
00147           assert(devices.size() == queue.size() && bool("ViennaCL expects one queue per device!"));
00148 
00149           //wrap queue vector into map
00150           std::map< cl_device_id, std::vector<cl_command_queue> > queues_map;
00151           for (vcl_size_t j = 0; j<devices.size(); ++j)
00152             queues_map[devices[j]].push_back(queue[j]);
00153 
00154           setup_context(i, c, devices, queues_map);
00155         }
00156 
00158         static void set_context_device_type(long i, cl_device_type t)
00159         {
00160           contexts_[i].default_device_type(t);
00161         }
00162 
00164         static void set_context_device_num(long i, vcl_size_t num)
00165         {
00166           contexts_[i].default_device_num(num);
00167         }
00168 
00170         static void set_context_platform_index(long i, vcl_size_t pf_index)
00171         {
00172           contexts_[i].platform_index(pf_index);
00173         }
00174 
00175       private:
00176         static long current_context_id_;
00177         static std::map<long, bool> initialized_;
00178         static std::map<long, viennacl::ocl::context> contexts_;
00179     };
00180 
00181     template <bool dummy>
00182     long backend<dummy>::current_context_id_ = 0;
00183 
00184     template <bool dummy>
00185     std::map<long, bool> backend<dummy>::initialized_;
00186 
00187     template <bool dummy>
00188     std::map<long, viennacl::ocl::context> backend<dummy>::contexts_;
00189 
00191 
00192     inline viennacl::ocl::context & current_context()
00193     {
00194       return viennacl::ocl::backend<>::current_context();
00195     }
00196 
00198     inline void switch_context(long i)
00199     {
00200       viennacl::ocl::backend<>::switch_context(i);
00201     }
00202 
00204     inline viennacl::ocl::context & get_context(long i)
00205     {
00206       return viennacl::ocl::backend<>::context(i);
00207     }
00208 
00210     inline void setup_context(long i,
00211                               std::vector<cl_device_id> const & devices)
00212     {
00213       viennacl::ocl::backend<>::setup_context(i, devices);
00214     }
00215 
00217     inline void setup_context(long i,
00218                               viennacl::ocl::device const & device)
00219     {
00220       std::vector<cl_device_id> device_id_array(1);
00221       device_id_array[0] = device.id();
00222       viennacl::ocl::backend<>::setup_context(i, device_id_array);
00223     }
00224 
00226     inline void setup_context(long i,
00227                               cl_context c,
00228                               std::vector<cl_device_id> const & devices,
00229                               std::map< cl_device_id, std::vector<cl_command_queue> > const & queues)
00230     {
00231       viennacl::ocl::backend<>::setup_context(i, c, devices, queues);
00232     }
00233 
00235     inline void setup_context(long i, cl_context c, std::vector<cl_device_id> const & devices, std::vector<cl_command_queue> const & queues)
00236     {
00237       viennacl::ocl::backend<>::setup_context(i, c, devices, queues);
00238     }
00239 
00241     inline void setup_context(long i, cl_context c, cl_device_id d, cl_command_queue q)
00242     {
00243       std::vector<cl_device_id> devices(1);
00244       std::vector<cl_command_queue> queues(1);
00245       devices[0] = d;
00246       queues[0] = q;
00247       viennacl::ocl::backend<>::setup_context(i, c, devices, queues);
00248     }
00249 
00251     inline void set_context_device_type(long i, cl_device_type dev_type)
00252     {
00253       viennacl::ocl::backend<>::set_context_device_type(i, dev_type);
00254     }
00255 
00257     inline void set_context_device_type(long i, viennacl::ocl::gpu_tag)
00258     {
00259       set_context_device_type(i, CL_DEVICE_TYPE_GPU);
00260     }
00261 
00263     inline void set_context_device_type(long i, viennacl::ocl::cpu_tag)
00264     {
00265       set_context_device_type(i, CL_DEVICE_TYPE_CPU);
00266     }
00267 
00269     inline void set_context_device_type(long i, viennacl::ocl::default_tag)
00270     {
00271       set_context_device_type(i, CL_DEVICE_TYPE_DEFAULT);
00272     }
00273 
00275     inline void set_context_device_type(long i, viennacl::ocl::accelerator_tag)
00276     {
00277       set_context_device_type(i, CL_DEVICE_TYPE_ACCELERATOR);
00278     }
00279 
00281     inline void set_context_device_num(long i, vcl_size_t num)
00282     {
00283       viennacl::ocl::backend<>::set_context_device_num(i, num);
00284     }
00285 
00286 
00292     inline void set_context_platform_index(long i, vcl_size_t pf_index)
00293     {
00294       viennacl::ocl::backend<>::set_context_platform_index(i, pf_index);
00295     }
00296 
00298 
00299     inline viennacl::ocl::command_queue & get_queue()
00300     {
00301       return viennacl::ocl::current_context().get_queue();
00302     }
00303 
00305     inline viennacl::ocl::command_queue & get_queue(viennacl::ocl::device d, unsigned int queue_id = 0)
00306     {
00307       return viennacl::ocl::current_context().get_queue(d.id(), queue_id);
00308     }
00309 
00311     inline viennacl::ocl::command_queue & get_queue(cl_device_id dev_id, unsigned int queue_id = 0)
00312     {
00313       return viennacl::ocl::current_context().get_queue(dev_id, queue_id);
00314     }
00315 
00316 
00318     inline viennacl::ocl::kernel & get_kernel(std::string const & prog_name, std::string const & kernel_name)
00319     {
00320       return viennacl::ocl::current_context().get_program(prog_name).get_kernel(kernel_name);
00321     }
00322 
00324     inline void switch_device(viennacl::ocl::device & d)
00325     {
00326       viennacl::ocl::current_context().switch_device(d);
00327     }
00328 
00330     inline viennacl::ocl::device const & current_device()
00331     {
00332       return viennacl::ocl::current_context().current_device();
00333     }
00334 
00335   } //ocl
00336 } //viennacl
00337 #endif