vector_proxy.hpp
Go to the documentation of this file.
1 /*!
2  * \brief Implements the dense matrix class for the gpu
3  *
4  * \author O. Krause
5  * \date 2016
6  *
7  *
8  * \par Copyright 1995-2015 Shark Development Team
9  *
10  * <BR><HR>
11  * This file is part of Shark.
12  * <http://image.diku.dk/shark/>
13  *
14  * Shark is free software: you can redistribute it and/or modify
15  * it under the terms of the GNU Lesser General Public License as published
16  * by the Free Software Foundation, either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * Shark is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public License
25  * along with Shark. If not, see <http://www.gnu.org/licenses/>.
26  *
27  */
28 #ifndef REMORA_GPU_VECTOR_PROXY_HPP
29 #define REMORA_GPU_VECTOR_PROXY_HPP
30 
31 #include "../expression_types.hpp"
32 #include "traits.hpp"
33 #include <boost/compute/iterator/strided_iterator.hpp>
34 #include <boost/compute/iterator/buffer_iterator.hpp>
35 
36 namespace remora{
37 
38 namespace detail{
39 template<class Arg, class T>
40 struct induced_vector_adaptor_element{
41  typedef T result_type;
42  Arg arg;
43  gpu::dense_vector_storage<T> storage;
44 };
45 
46 template<class Arg1, class Arg2,class T>
47 boost::compute::detail::meta_kernel& operator<< (
48  boost::compute::detail::meta_kernel& k,
49  induced_vector_adaptor_element<Arg1, Arg2, T> const& e
50 ){
51  return k<< k.get_buffer_identifier<T>(e.storage.buffer, boost::compute::memory_object::global_memory)
52  <<" [ "<<e.storage.offset <<"+("<<e.arg <<")*"<<e.storage.stride<<']';
53 }
54 }
55 
56 template<class T>
57 class dense_vector_adaptor<T,gpu_tag>: public vector_expression<dense_vector_adaptor<T, gpu_tag>, gpu_tag > {
58 public:
59  typedef std::size_t size_type;
60  typedef typename std::remove_const<T>::type value_type;
61  typedef value_type const& const_reference;
62  typedef T& reference;
63 
64  typedef dense_vector_adaptor<T const> const_closure_type;
65  typedef dense_vector_adaptor closure_type;
66  typedef gpu::dense_vector_storage<T> storage_type;
67  typedef gpu::dense_vector_storage<value_type const> const_storage_type;
68  typedef elementwise<dense_tag> evaluation_category;
69 
70  // Construction and destruction
71 
72  /// \brief Constructor of a proxy from a Dense VectorExpression
73  ///
74  /// Be aware that the expression must live longer than the proxy!
75  /// \param expression The Expression from which to construct the Proxy
76  template<class E>
77  dense_vector_adaptor(vector_expression<E, gpu_tag> const& expression)
78  : m_storage(expression().raw_storage())
79  , m_queue(&expression().queue())
80  , m_size(expression().size()){}
81 
82  /// \brief Constructor of a proxy from a Dense VectorExpression
83  ///
84  /// Be aware that the expression must live longer than the proxy!
85  /// \param expression The Expression from which to construct the Proxy
86  template<class E>
87  dense_vector_adaptor(vector_expression<E,gpu_tag>& expression)
88  : m_storage(expression().raw_storage())
89  , m_queue(&expression().queue())
90  , m_size(expression().size()){}
91 
92 
93  template<class E>
94  dense_vector_adaptor(matrix_expression<E, gpu_tag> const& expression)
95  : m_size(expression().size1() * expression().size2()), m_queue(&expression().queue()){
96  gpu::dense_matrix_storage<T> storage = expression().raw_storage();
97  m_storage.buffer = storage.buffer;
98  m_storage.offset = storage.offset;
99  m_storage.stride = storage.leading_dimension;
100  }
101 
102  template<class E>
103  dense_vector_adaptor(matrix_expression<E, gpu_tag>& expression)
104  : m_size(expression().size1() * expression().size2()), m_queue(&expression().queue()){
105  gpu::dense_matrix_storage<T> storage = expression().raw_storage();
106  m_storage.buffer = storage.buffer;
107  m_storage.offset = storage.offset;
108  m_storage.stride = storage.leading_dimension;
109  }
110 
111  /// \brief Copy-constructor
112  /// \param v is the proxy to be copied
113  template<class U>
114  dense_vector_adaptor(dense_vector_adaptor<U> const& v)
115  : m_storage(v.raw_storage())
116  , m_queue(&v.queue())
117  , m_size(v.size()){}
118 
119  /// \brief Return the size of the vector.
120  size_type size() const {
121  return m_size;
122  }
123 
124  ///\brief Returns the underlying storage_type structure for low level access
125  storage_type raw_storage() const{
126  return m_storage;
127  }
128 
129  boost::compute::command_queue& queue(){
130  return *m_queue;
131  }
132  // --------------
133  // Element access
134  // --------------
135 
136  /// \brief Return a const reference to the element \f$i\f$
137  /// \param i index of the element
138  template <class IndexExpr>
139  induced_vector_adaptor_element<IndexExpr,T> operator()(IndexExpr const& i){
140  return {i, m_storage};
141  }
142 
143  // --------------
144  // ITERATORS
145  // --------------
146 
147 
148  typedef boost::compute::strided_iterator<boost::compute::buffer_iterator<T> > iterator;
149  typedef boost::compute::strided_iterator<boost::compute::buffer_iterator<T> > const_iterator;
150 
151  /// \brief return an iterator on the first element of the vector
152  const_iterator begin() const {
153  return const_iterator(boost::compute::buffer_iterator<T>(m_storage.buffer, m_storage.offset),m_storage.stride);
154  }
155 
156  /// \brief return an iterator after the last element of the vector
157  const_iterator end() const {
158  return const_iterator(
159  boost::compute::buffer_iterator<T>(m_storage.buffer, m_size * m_storage.stride + m_storage.offset)
160  ,m_storage.stride
161  );
162  }
163 
164  /// \brief Return an iterator on the first element of the vector
165  iterator begin(){
166  return iterator(boost::compute::buffer_iterator<T>(m_storage.buffer, m_storage.offset),m_storage.stride);
167  }
168 
169  /// \brief Return an iterator at the end of the vector
170  iterator end(){
171  return iterator(
172  boost::compute::buffer_iterator<T>(m_storage.buffer, m_size * m_storage.stride + m_storage.offset)
173  ,m_storage.stride
174  );
175  }
176 private:
177  storage_type m_storage;
178  boost::compute::command_queue* m_queue;
179  size_type m_size;
180 };
181 
182 }
183 
184 #endif