• Main Page
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

/data/development/ViennaCL/ViennaCL-1.1.2/viennacl/ocl/context.hpp

Go to the documentation of this file.
00001 /* =======================================================================
00002    Copyright (c) 2010, Institute for Microelectronics, TU Vienna.
00003    http://www.iue.tuwien.ac.at
00004                              -----------------
00005                      ViennaCL - The Vienna Computing Library
00006                              -----------------
00007                             
00008    authors:    Karl Rupp                          rupp@iue.tuwien.ac.at
00009                Florian Rudolf                     flo.rudy+viennacl@gmail.com
00010                Josef Weinbub                      weinbub@iue.tuwien.ac.at
00011 
00012    license:    MIT (X11), see file LICENSE in the ViennaCL base directory
00013 ======================================================================= */
00014 
00015 #ifndef _VIENNACL_CONTEXT_HPP_
00016 #define _VIENNACL_CONTEXT_HPP_
00017 
00022 #ifdef __APPLE__
00023 #include <OpenCL/cl.h>
00024 #else
00025 #include <CL/cl.h>
00026 #endif
00027 
00028 #include <algorithm>
00029 #include <vector>
00030 #include <map>
00031 #include "viennacl/ocl/forwards.h"
00032 #include "viennacl/ocl/handle.hpp"
00033 #include "viennacl/ocl/program.hpp"
00034 #include "viennacl/ocl/device.hpp"
00035 #include "viennacl/ocl/platform.hpp"
00036 #include "viennacl/ocl/command_queue.hpp"
00037 
00038 namespace viennacl
00039 {
00040   namespace ocl
00041   {
00042     class context
00043     {
00044       typedef std::vector< viennacl::ocl::program >   ProgramContainer;
00045       
00046       public:
00047         context() : initialized_(false), device_type_(CL_DEVICE_TYPE_DEFAULT), current_device_id(0) {}
00048         
00049         
00051 
00052         cl_device_type default_device_type()
00053         {
00054           return device_type_;
00055         }
00056         
00058         void default_device_type(cl_device_type dtype) 
00059         { 
00060           #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_CONTEXT)
00061           std::cout << "ViennaCL: Setting new device type for context " << h_ << std::endl;
00062           #endif
00063           if (!initialized_)
00064             device_type_ = dtype; //assume that the user provided a correct value
00065         }
00066         
00068 
00069         std::vector<viennacl::ocl::device> const & devices() const
00070         {
00071           return devices_;
00072         }
00073         
00075         viennacl::ocl::device const & current_device() const
00076         {
00077           //std::cout << "Current device id in context: " << current_device_id << std::endl;
00078           return devices_[current_device_id];
00079         }
00080         
00082         void switch_device(size_t i)
00083         {
00084           assert(i >= 0 && i < devices_.size());
00085           current_device_id = i;
00086         }
00087 
00089         void switch_device(viennacl::ocl::device const & d)
00090         {
00091           #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_CONTEXT)
00092           std::cout << "ViennaCL: Setting new current device for context " << h_ << std::endl;
00093           #endif
00094           bool found = false;
00095           for (size_t i=0; i<devices_.size(); ++i)
00096           {
00097             if (devices_[i] == d)
00098             {
00099               found = true;
00100               current_device_id = i;
00101               break;
00102             }
00103           }
00104           if (found == false)
00105             std::cerr << "ViennaCL: Warning: Could not set device " << d.name() << " for context." << std::endl;
00106         }
00107         
00109         void add_device(viennacl::ocl::device const & d)
00110         {
00111           assert(!initialized_ && "Device must be added to context before it is initialized!");
00112           #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_CONTEXT)
00113           std::cout << "ViennaCL: Adding new device to context " << h_ << std::endl;
00114           #endif
00115           if (std::find(devices_.begin(), devices_.end(), d) != devices_.end())
00116             devices_.push_back(d);
00117         }
00118 
00120         void add_device(cl_device_id d)
00121         {
00122           assert(!initialized_ && "Device must be added to context before it is initialized!");
00123           add_device(viennacl::ocl::device(d));
00124         }
00125 
00126 
00128         
00130         void init()
00131         {
00132           init_new();
00133         }
00134 
00136         void init(cl_context c)
00137         {
00138           init_existing(c);
00139         }
00140 
00141 /*        void existing_context(cl_context context_id)
00142         {
00143           assert(!initialized_ && "ViennaCL: FATAL error: Provided a new context for an already initialized context.");
00144           #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_CONTEXT)
00145           std::cout << "ViennaCL: Reusing existing context " << h_ << std::endl;
00146           #endif
00147           h_ = context_id;
00148         }*/
00149         
00151 
00157         viennacl::ocl::handle<cl_mem> create_memory(cl_mem_flags flags, unsigned int size, void * ptr = NULL)
00158         {
00159           #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_CONTEXT)
00160           std::cout << "ViennaCL: Creating memory of size " << size << " for context " << h_ << std::endl;
00161           #endif
00162           if (ptr)
00163             flags |= CL_MEM_COPY_HOST_PTR;
00164           cl_int err;
00165           viennacl::ocl::handle<cl_mem> mem = clCreateBuffer(handle(), flags, size, ptr, &err);
00166           VIENNACL_ERR_CHECK(err);
00167           return mem;
00168         }
00169 
00175         template < typename SCALARTYPE, typename A, template <typename, typename> class VectorType >
00176         viennacl::ocl::handle<cl_mem> create_memory(cl_mem_flags flags, const VectorType<SCALARTYPE, A> & _buffer)
00177         {
00178           return create_memory(flags, static_cast<unsigned int>(sizeof(SCALARTYPE) * _buffer.size()), (void*)&_buffer[0]);
00179         }
00180         
00182         
00184         void add_queue(cl_device_id dev, cl_command_queue q)
00185         {
00186           #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_CONTEXT)
00187           std::cout << "ViennaCL: Adding existing queue " << q << " for device " << dev << " to context " << h_ << std::endl;
00188           #endif
00189           queues_[dev].push_back(viennacl::ocl::command_queue(q, dev));
00190         }
00191         
00193         void add_queue(cl_device_id dev)
00194         {
00195           #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_CONTEXT)
00196           std::cout << "ViennaCL: Adding new queue for device " << dev << " to context " << h_ << std::endl;
00197           #endif
00198           cl_int err;
00199           viennacl::ocl::handle<cl_command_queue> temp = clCreateCommandQueue(handle(), dev, 0, &err);
00200           VIENNACL_ERR_CHECK(err);
00201           
00202           queues_[dev].push_back(viennacl::ocl::command_queue(temp, dev));
00203         }
00204 
00206         void add_queue(viennacl::ocl::device d) { add_queue(d.id()); }
00207 
00208         //get queue for default device:
00209         viennacl::ocl::command_queue & get_queue()
00210         {
00211           return queues_[devices_[current_device_id].id()][0];
00212         }
00213         
00214         //get a particular queue:
00216         viennacl::ocl::command_queue & get_queue(cl_device_id dev, size_t i = 0)
00217         {
00218           assert(i >= 0 && i < queues_.size() && "In class 'context': id invalid in get_queue()");
00219           #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_CONTEXT)
00220           std::cout << "ViennaCL: Getting queue " << i << " for device " << dev << " in context " << h_ << std::endl;
00221           #endif
00222           unsigned int device_index;
00223           for (device_index = 0; device_index < devices_.size(); ++device_index)
00224           {
00225             if (devices_[device_index] == dev)
00226               break;
00227           }
00228           
00229           assert(device_index < devices_.size() && "Device not within context");
00230           
00231           return queues_[devices_[device_index].id()][i];
00232         }
00233         
00235 
00237         viennacl::ocl::program & add_program(cl_program p, std::string const & prog_name)
00238         {
00239           programs_.push_back(viennacl::ocl::program(p, prog_name));
00240           return programs_.back();
00241         }
00242         
00245         viennacl::ocl::program & add_program(std::string const & source, std::string const & prog_name)
00246         {
00247           const char * source_text = source.c_str();
00248           size_t source_size = source.size();
00249           cl_int err;
00250           
00251           #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_CONTEXT)
00252           std::cout << "ViennaCL: Adding program '" << prog_name << "' to context " << h_ << std::endl;
00253           #endif
00254           
00255           viennacl::ocl::handle<cl_program> temp = clCreateProgramWithSource(h_, 1, (const char **)&source_text, &source_size, &err);
00256           VIENNACL_ERR_CHECK(err);
00257           
00258           err = clBuildProgram(temp, 0, NULL, NULL, NULL, NULL);
00259           #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_BUILD)
00260             char buffer[1024];
00261             cl_build_status status;
00262             clGetProgramBuildInfo(temp, devices_[0].id(), CL_PROGRAM_BUILD_STATUS, sizeof(cl_build_status), &status, NULL);
00263             clGetProgramBuildInfo(temp, devices_[0].id(), CL_PROGRAM_BUILD_LOG, sizeof(char)*1024, &buffer, NULL);
00264             std::cout << "Build Scalar: Err = " << err << " Status = " << status << std::endl;
00265             std::cout << "Log: " << buffer << std::endl;
00266           #endif
00267           VIENNACL_ERR_CHECK(err);
00268 
00269           programs_.push_back(viennacl::ocl::program(temp, prog_name));
00270           
00271           return programs_.back();
00272         }
00273         
00275         viennacl::ocl::program & get_program(std::string const & name)
00276         {
00277           #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_CONTEXT)
00278           std::cout << "ViennaCL: Getting program '" << name << "' from context " << h_ << std::endl;
00279           #endif
00280           for (ProgramContainer::iterator it = programs_.begin();
00281                 it != programs_.end();
00282                 ++it)
00283           {
00284             if (it->name() == name)
00285               return *it;
00286           }
00287           std::cerr << "Could not find program '" << name << "'" << std::endl;
00288           assert(!"In class 'context': name invalid in get_program()");
00289           return programs_[0];  //return a defined object
00290         }
00291         
00293         viennacl::ocl::program & get_program(size_t id)
00294         {
00295           assert(id >= 0 && id < programs_.size() && "In class 'context': id invalid in get_program()");
00296           return programs_[id];
00297         }
00298         
00300         size_t program_num() { return programs_.size(); }
00301 
00303         size_t device_num() { return devices_.size(); }
00304         
00306         const viennacl::ocl::handle<cl_context> & handle() const { return h_; }
00307         
00309         bool operator<(context const & other) const
00310         {
00311           return h_ < other.h_;
00312         }
00313         
00314       private:
00316         void init_new()
00317         {
00318           assert(!initialized_ && "ViennaCL FATAL error: Context already created!");
00319 
00320           #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_CONTEXT)
00321           std::cout << "ViennaCL: Initializing new ViennaCL context." << std::endl;
00322           #endif
00323           
00324           cl_int err;
00325           std::vector<cl_device_id> device_id_array;
00326           if (devices_.empty()) //get the default device if user has not yet specified a list of devices
00327           {
00328             //create an OpenCL context for the provided devices:
00329             #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_CONTEXT)
00330             std::cout << "ViennaCL: Setting all devices for context..." << std::endl;
00331             #endif
00332             
00333             platform pf;
00334             std::vector<device> devices = pf.devices(device_type_);
00335             #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_CONTEXT)
00336             std::cout << "ViennaCL: Number of devices for context: " << devices.size() << std::endl;
00337             #endif
00338             for (size_t i=0; i<devices.size(); ++i)
00339               devices_.push_back(devices[i]);
00340             
00341             if (devices.size() == 0)
00342             {
00343               std::cerr << "ViennaCL: FATAL ERROR: No devices of type '";
00344               switch (device_type_)
00345               {
00346                 case CL_DEVICE_TYPE_CPU:          std::cout << "CPU"; break;
00347                 case CL_DEVICE_TYPE_GPU:          std::cout << "CPU"; break;
00348                 case CL_DEVICE_TYPE_ACCELERATOR:  std::cout << "ACCELERATOR"; break;
00349                 case CL_DEVICE_TYPE_DEFAULT:      std::cout << "DEFAULT"; break;
00350                 default:
00351                   std::cout << "UNKNOWN" << std::endl;
00352               }
00353               std::cout << "' found!" << std::endl;
00354             }
00355           }
00356           
00357           //extract list of device ids:
00358           for (std::vector< viennacl::ocl::device >::const_iterator iter = devices_.begin();
00359                                                                     iter != devices_.end();
00360                                                                   ++iter)
00361             device_id_array.push_back(iter->id());
00362             
00363           h_ = clCreateContext(0, device_id_array.size(), &(device_id_array[0]), NULL, NULL, &err);
00364           VIENNACL_ERR_CHECK(err);
00365           
00366           initialized_ = true;
00367           #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_CONTEXT)
00368           std::cout << "ViennaCL: Initialization of new ViennaCL context done." << std::endl;
00369           #endif
00370         }
00371         
00373         void init_existing(cl_context c)
00374         {
00375           assert(!initialized_ && "ViennaCL FATAL error: Context already created!");
00376           #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_CONTEXT)
00377           std::cout << "ViennaCL: Initialization of ViennaCL context from existing context." << std::endl;
00378           #endif
00379           
00380           //set context handle:
00381           h_ = c;
00382           
00383           if (devices_.empty())
00384           {
00385             //get devices for context:
00386             cl_int err;
00387             cl_uint num_devices;
00388             size_t temp;
00389             //Note: The obvious
00390             //  err = clGetContextInfo(h_, CL_CONTEXT_NUM_DEVICES, sizeof(cl_uint), &num_devices, NULL);
00391             //does not work with NVIDIA OpenCL stack!
00392             err = clGetContextInfo(h_, CL_CONTEXT_DEVICES, VIENNACL_OCL_MAX_DEVICE_NUM * sizeof(cl_device_id), NULL, &temp);
00393             VIENNACL_ERR_CHECK(err);
00394             assert(temp > 0 && "ViennaCL: FATAL error: Provided context does not contain any devices!");
00395             num_devices = temp / sizeof(cl_device_id);
00396             
00397             #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_CONTEXT)
00398             std::cout << "ViennaCL: Reusing context with " << num_devices << " devices." << std::endl;
00399             #endif
00400             
00401             std::vector<cl_device_id> device_ids(num_devices);
00402             err = clGetContextInfo(h_, CL_CONTEXT_DEVICES, num_devices * sizeof(cl_device_id), &(device_ids[0]), NULL);
00403             VIENNACL_ERR_CHECK(err);
00404             
00405             for (size_t i=0; i<num_devices; ++i)
00406               devices_.push_back(viennacl::ocl::device(device_ids[i]));
00407           }
00408           current_device_id = 0;
00409           
00410           initialized_ = true;
00411           #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_CONTEXT)
00412           std::cout << "ViennaCL: Initialization of ViennaCL context from existing context done." << std::endl;
00413           #endif
00414         }       
00415         
00416         
00417         bool initialized_;
00418         cl_device_type device_type_;
00419         viennacl::ocl::handle<cl_context> h_;
00420         std::vector< viennacl::ocl::device > devices_;
00421         unsigned int current_device_id;
00422         ProgramContainer programs_;
00423         std::map< cl_device_id, std::vector< viennacl::ocl::command_queue> > queues_;
00424     }; //context
00425     
00426   }
00427 }
00428 
00429 #endif

Generated on Sat May 21 2011 20:36:50 for ViennaCL - The Vienna Computing Library by  doxygen 1.7.1