ViennaCL - The Vienna Computing Library  1.5.2
viennacl/backend/util.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_BACKEND_UTIL_HPP
00002 #define VIENNACL_BACKEND_UTIL_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 <cassert>
00027 
00028 #include "viennacl/forwards.h"
00029 #include "viennacl/backend/mem_handle.hpp"
00030 
00031 #ifdef VIENNACL_WITH_OPENCL
00032   #include "viennacl/backend/opencl.hpp"
00033 #endif
00034 
00035 
00036 namespace viennacl
00037 {
00038   namespace backend
00039   {
00040 
00041 
00042 
00043     namespace detail
00044     {
00045 
00047       template <typename T>
00048       struct convert_to_opencl
00049       {
00050         typedef T    type;
00051         enum { special = 0 };
00052       };
00053 
00054 #ifdef VIENNACL_WITH_OPENCL
00055       template <>
00056       struct convert_to_opencl<unsigned int>
00057       {
00058         typedef cl_uint    type;
00059         //enum { special = (sizeof(unsigned int) != sizeof(cl_uint)) };
00060         enum { special = 1 };
00061       };
00062 
00063       template <>
00064       struct convert_to_opencl<int>
00065       {
00066         typedef cl_int    type;
00067         //enum { special = (sizeof(int) != sizeof(cl_int)) };
00068         enum { special = 1 };
00069       };
00070 
00071 
00072       template <>
00073       struct convert_to_opencl<unsigned long>
00074       {
00075         typedef cl_ulong    type;
00076         //enum { special = (sizeof(unsigned long) != sizeof(cl_ulong)) };
00077         enum { special = 1 };
00078       };
00079 
00080       template <>
00081       struct convert_to_opencl<long>
00082       {
00083         typedef cl_long    type;
00084         //enum { special = (sizeof(long) != sizeof(cl_long)) };
00085         enum { special = 1 };
00086       };
00087 #endif
00088 
00089 
00090     } //namespace detail
00091 
00092 
00094     template <typename T, bool special = detail::convert_to_opencl<T>::special>
00095     class typesafe_host_array
00096     {
00097         typedef T                                              cpu_type;
00098         typedef typename detail::convert_to_opencl<T>::type    target_type;
00099 
00100       public:
00101         explicit typesafe_host_array() : bytes_buffer_(NULL), buffer_size_(0) {}
00102 
00103         explicit typesafe_host_array(mem_handle const & handle, vcl_size_t num = 0) : bytes_buffer_(NULL), buffer_size_(sizeof(cpu_type) * num)
00104         {
00105           resize(handle, num);
00106         }
00107 
00108         ~typesafe_host_array() { delete[] bytes_buffer_; }
00109 
00110         //
00111         // Resize functionality
00112         //
00113 
00115         void raw_resize(mem_handle const & /*handle*/, vcl_size_t num)
00116         {
00117           buffer_size_ = sizeof(cpu_type) * num;
00118 
00119           if (num > 0)
00120           {
00121             delete[] bytes_buffer_;
00122 
00123             bytes_buffer_ = new char[buffer_size_];
00124           }
00125         }
00126 
00128         void resize(mem_handle const & handle, vcl_size_t num)
00129         {
00130           raw_resize(handle, num);
00131 
00132           if (num > 0)
00133           {
00134             for (vcl_size_t i=0; i<buffer_size_; ++i)
00135               bytes_buffer_[i] = 0;
00136           }
00137         }
00138 
00139         //
00140         // Setter and Getter
00141         //
00142 
00143         template <typename U>
00144         void set(vcl_size_t index, U value)
00145         {
00146           reinterpret_cast<cpu_type *>(bytes_buffer_)[index] = static_cast<cpu_type>(value);
00147         }
00148 
00149         void * get() { return reinterpret_cast<void *>(bytes_buffer_); }
00150         cpu_type operator[](vcl_size_t index) const
00151         {
00152           assert(index < size() && bool("index out of bounds"));
00153 
00154           return reinterpret_cast<cpu_type *>(bytes_buffer_)[index];
00155         }
00156 
00157         vcl_size_t raw_size() const { return buffer_size_; }
00158         vcl_size_t element_size() const
00159         {
00160           return sizeof(cpu_type);
00161         }
00162         vcl_size_t size() const { return buffer_size_ / element_size(); }
00163 
00164       private:
00165         char * bytes_buffer_;
00166         vcl_size_t buffer_size_;
00167     };
00168 
00169 
00170 
00171 
00173     template <typename T>
00174     class typesafe_host_array<T, true>
00175     {
00176         typedef T                                              cpu_type;
00177         typedef typename detail::convert_to_opencl<T>::type    target_type;
00178 
00179       public:
00180         explicit typesafe_host_array() : convert_to_opencl_( (default_memory_type() == OPENCL_MEMORY) ? true : false), bytes_buffer_(NULL), buffer_size_(0) {}
00181 
00182         explicit typesafe_host_array(mem_handle const & handle, vcl_size_t num = 0) : convert_to_opencl_(false), bytes_buffer_(NULL), buffer_size_(sizeof(cpu_type) * num)
00183         {
00184           resize(handle, num);
00185         }
00186 
00187         ~typesafe_host_array() { delete[] bytes_buffer_; }
00188 
00189         //
00190         // Resize functionality
00191         //
00192 
00194         void raw_resize(mem_handle const & handle, vcl_size_t num)
00195         {
00196           buffer_size_ = sizeof(cpu_type) * num;
00197           (void)handle; //silence unused variable warning if compiled without OpenCL support
00198 
00199 #ifdef VIENNACL_WITH_OPENCL
00200           memory_types mem_type = handle.get_active_handle_id();
00201           if (mem_type == MEMORY_NOT_INITIALIZED)
00202             mem_type = default_memory_type();
00203 
00204           if (mem_type == OPENCL_MEMORY)
00205           {
00206             convert_to_opencl_ = true;
00207             buffer_size_ = sizeof(target_type) * num;
00208           }
00209 #endif
00210 
00211           if (num > 0)
00212           {
00213             delete[] bytes_buffer_;
00214 
00215             bytes_buffer_ = new char[buffer_size_];
00216           }
00217         }
00218 
00220         void resize(mem_handle const & handle, vcl_size_t num)
00221         {
00222           raw_resize(handle, num);
00223 
00224           if (num > 0)
00225           {
00226             for (vcl_size_t i=0; i<buffer_size_; ++i)
00227               bytes_buffer_[i] = 0;
00228           }
00229         }
00230 
00231         //
00232         // Setter and Getter
00233         //
00234 
00235         template <typename U>
00236         void set(vcl_size_t index, U value)
00237         {
00238 #ifdef VIENNACL_WITH_OPENCL
00239           if (convert_to_opencl_)
00240             reinterpret_cast<target_type *>(bytes_buffer_)[index] = static_cast<target_type>(value);
00241           else
00242 #endif
00243             reinterpret_cast<cpu_type *>(bytes_buffer_)[index] = static_cast<cpu_type>(value);
00244         }
00245 
00246         void * get() { return reinterpret_cast<void *>(bytes_buffer_); }
00247         cpu_type operator[](vcl_size_t index) const
00248         {
00249           assert(index < size() && bool("index out of bounds"));
00250 #ifdef VIENNACL_WITH_OPENCL
00251           if (convert_to_opencl_)
00252             return static_cast<cpu_type>(reinterpret_cast<target_type *>(bytes_buffer_)[index]);
00253 #endif
00254           return reinterpret_cast<cpu_type *>(bytes_buffer_)[index];
00255         }
00256 
00257         vcl_size_t raw_size() const { return buffer_size_; }
00258         vcl_size_t element_size() const
00259         {
00260 #ifdef VIENNACL_WITH_OPENCL
00261           if (convert_to_opencl_)
00262             return sizeof(target_type);
00263 #endif
00264           return sizeof(cpu_type);
00265         }
00266         vcl_size_t size() const { return buffer_size_ / element_size(); }
00267 
00268       private:
00269         bool convert_to_opencl_;
00270         char * bytes_buffer_;
00271         vcl_size_t buffer_size_;
00272     };
00273 
00274   } //backend
00275 
00276 
00277 } //viennacl
00278 #endif