ViennaCL - The Vienna Computing Library  1.5.0
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-2013, 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             if (bytes_buffer_)
00122               delete[] bytes_buffer_;
00123 
00124             bytes_buffer_ = new char[buffer_size_];
00125           }
00126         }
00127 
00129         void resize(mem_handle const & handle, vcl_size_t num)
00130         {
00131           raw_resize(handle, num);
00132 
00133           if (num > 0)
00134           {
00135             for (vcl_size_t i=0; i<buffer_size_; ++i)
00136               bytes_buffer_[i] = 0;
00137           }
00138         }
00139 
00140         //
00141         // Setter and Getter
00142         //
00143 
00144         template <typename U>
00145         void set(vcl_size_t index, U value)
00146         {
00147           reinterpret_cast<cpu_type *>(bytes_buffer_)[index] = static_cast<cpu_type>(value);
00148         }
00149 
00150         void * get() { return reinterpret_cast<void *>(bytes_buffer_); }
00151         cpu_type operator[](vcl_size_t index) const
00152         {
00153           assert(index < size() && bool("index out of bounds"));
00154 
00155           return reinterpret_cast<cpu_type *>(bytes_buffer_)[index];
00156         }
00157 
00158         vcl_size_t raw_size() const { return buffer_size_; }
00159         vcl_size_t element_size() const
00160         {
00161           return sizeof(cpu_type);
00162         }
00163         vcl_size_t size() const { return buffer_size_ / element_size(); }
00164 
00165       private:
00166         char * bytes_buffer_;
00167         vcl_size_t buffer_size_;
00168     };
00169 
00170 
00171 
00172 
00174     template <typename T>
00175     class typesafe_host_array<T, true>
00176     {
00177         typedef T                                              cpu_type;
00178         typedef typename detail::convert_to_opencl<T>::type    target_type;
00179 
00180       public:
00181         explicit typesafe_host_array() : convert_to_opencl_( (default_memory_type() == OPENCL_MEMORY) ? true : false), bytes_buffer_(NULL), buffer_size_(0) {}
00182 
00183         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)
00184         {
00185           resize(handle, num);
00186         }
00187 
00188         ~typesafe_host_array() { delete[] bytes_buffer_; }
00189 
00190         //
00191         // Resize functionality
00192         //
00193 
00195         void raw_resize(mem_handle const & handle, vcl_size_t num)
00196         {
00197           buffer_size_ = sizeof(cpu_type) * num;
00198           (void)handle; //silence unused variable warning if compiled without OpenCL support
00199 
00200 #ifdef VIENNACL_WITH_OPENCL
00201           memory_types mem_type = handle.get_active_handle_id();
00202           if (mem_type == MEMORY_NOT_INITIALIZED)
00203             mem_type = default_memory_type();
00204 
00205           if (mem_type == OPENCL_MEMORY)
00206           {
00207             convert_to_opencl_ = true;
00208             buffer_size_ = sizeof(target_type) * num;
00209           }
00210 #endif
00211 
00212           if (num > 0)
00213           {
00214             if (bytes_buffer_)
00215               delete[] bytes_buffer_;
00216 
00217             bytes_buffer_ = new char[buffer_size_];
00218           }
00219         }
00220 
00222         void resize(mem_handle const & handle, vcl_size_t num)
00223         {
00224           raw_resize(handle, num);
00225 
00226           if (num > 0)
00227           {
00228             for (vcl_size_t i=0; i<buffer_size_; ++i)
00229               bytes_buffer_[i] = 0;
00230           }
00231         }
00232 
00233         //
00234         // Setter and Getter
00235         //
00236 
00237         template <typename U>
00238         void set(vcl_size_t index, U value)
00239         {
00240 #ifdef VIENNACL_WITH_OPENCL
00241           if (convert_to_opencl_)
00242             reinterpret_cast<target_type *>(bytes_buffer_)[index] = static_cast<target_type>(value);
00243           else
00244 #endif
00245             reinterpret_cast<cpu_type *>(bytes_buffer_)[index] = static_cast<cpu_type>(value);
00246         }
00247 
00248         void * get() { return reinterpret_cast<void *>(bytes_buffer_); }
00249         cpu_type operator[](vcl_size_t index) const
00250         {
00251           assert(index < size() && bool("index out of bounds"));
00252 #ifdef VIENNACL_WITH_OPENCL
00253           if (convert_to_opencl_)
00254             return static_cast<cpu_type>(reinterpret_cast<target_type *>(bytes_buffer_)[index]);
00255 #endif
00256           return reinterpret_cast<cpu_type *>(bytes_buffer_)[index];
00257         }
00258 
00259         vcl_size_t raw_size() const { return buffer_size_; }
00260         vcl_size_t element_size() const
00261         {
00262 #ifdef VIENNACL_WITH_OPENCL
00263           if (convert_to_opencl_)
00264             return sizeof(target_type);
00265 #endif
00266           return sizeof(cpu_type);
00267         }
00268         vcl_size_t size() const { return buffer_size_ / element_size(); }
00269 
00270       private:
00271         bool convert_to_opencl_;
00272         char * bytes_buffer_;
00273         vcl_size_t buffer_size_;
00274     };
00275 
00276   } //backend
00277 
00278 
00279 } //viennacl
00280 #endif