Kokkos Core Kernels Package  Version of the Day
Kokkos_Vector.hpp
1 /*
2 //@HEADER
3 // ************************************************************************
4 //
5 // Kokkos v. 2.0
6 // Copyright (2014) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact H. Carter Edwards (hcedwar@sandia.gov)
39 //
40 // ************************************************************************
41 //@HEADER
42 */
43 
44 #ifndef KOKKOS_VECTOR_HPP
45 #define KOKKOS_VECTOR_HPP
46 
47 #include <Kokkos_Core_fwd.hpp>
48 #include <Kokkos_DualView.hpp>
49 
50 /* Drop in replacement for std::vector based on Kokkos::DualView
51  * Most functions only work on the host (it will not compile if called from device kernel)
52  *
53  */
54  namespace Kokkos {
55 
56 template< class Scalar, class Arg1Type = void>
57 class vector : public DualView<Scalar*,LayoutLeft,Arg1Type> {
58 
59  typedef Scalar value_type;
60  typedef Scalar* pointer;
61  typedef const Scalar* const_pointer;
62  typedef Scalar* reference;
63  typedef const Scalar* const_reference;
64  typedef Scalar* iterator;
65  typedef const Scalar* const_iterator;
66 
67 private:
68  size_t _size;
69  typedef size_t size_type;
70  float _extra_storage;
71  typedef DualView<Scalar*,LayoutLeft,Arg1Type> DV;
72 
73 
74 public:
75 #ifdef KOKKOS_CUDA_USE_UVM
76  KOKKOS_INLINE_FUNCTION Scalar& operator() (int i) const {return DV::h_view(i);};
77  KOKKOS_INLINE_FUNCTION Scalar& operator[] (int i) const {return DV::h_view(i);};
78 #else
79  inline Scalar& operator() (int i) const {return DV::h_view(i);};
80  inline Scalar& operator[] (int i) const {return DV::h_view(i);};
81 #endif
82 
83  /* Member functions which behave like std::vector functions */
84 
85  vector():DV() {
86  _size = 0;
87  _extra_storage = 1.1;
88  DV::modified_host() = 1;
89  };
90 
91 
92  vector(int n, Scalar val=Scalar()):DualView<Scalar*,LayoutLeft,Arg1Type>("Vector",size_t(n*(1.1))) {
93  _size = n;
94  _extra_storage = 1.1;
95  DV::modified_host() = 1;
96 
97  assign(n,val);
98  }
99 
100 
101  void resize(size_t n) {
102  if(n>=capacity())
103  DV::resize(size_t (n*_extra_storage));
104  _size = n;
105  }
106 
107  void resize(size_t n, const Scalar& val) {
108  assign(n,val);
109  }
110 
111  void assign (size_t n, const Scalar& val) {
112 
113  /* Resize if necessary (behavour of std:vector) */
114 
115  if(n>capacity())
116  DV::resize(size_t (n*_extra_storage));
117  _size = n;
118 
119  /* Assign value either on host or on device */
120 
121  if( DV::modified_host() >= DV::modified_device() ) {
122  set_functor_host f(DV::h_view,val);
123  parallel_for(n,f);
124  DV::t_host::execution_space::fence();
125  DV::modified_host()++;
126  } else {
127  set_functor f(DV::d_view,val);
128  parallel_for(n,f);
129  DV::t_dev::execution_space::fence();
130  DV::modified_device()++;
131  }
132  }
133 
134  void reserve(size_t n) {
135  DV::resize(size_t (n*_extra_storage));
136  }
137 
138  void push_back(Scalar val) {
139  DV::modified_host()++;
140  if(_size == capacity()) {
141  size_t new_size = _size*_extra_storage;
142  if(new_size == _size) new_size++;
143  DV::resize(new_size);
144  }
145 
146  DV::h_view(_size) = val;
147  _size++;
148 
149  };
150 
151  void pop_back() {
152  _size--;
153  };
154 
155  void clear() {
156  _size = 0;
157  }
158 
159  size_type size() const {return _size;};
160  size_type max_size() const {return 2000000000;}
161  size_type capacity() const {return DV::capacity();};
162  bool empty() const {return _size==0;};
163 
164  iterator begin() const {return &DV::h_view(0);};
165 
166  iterator end() const {return &DV::h_view(_size);};
167 
168 
169  /* std::algorithms wich work originally with iterators, here they are implemented as member functions */
170 
171  size_t
172  lower_bound (const size_t& start,
173  const size_t& theEnd,
174  const Scalar& comp_val) const
175  {
176  int lower = start; // FIXME (mfh 24 Apr 2014) narrowing conversion
177  int upper = _size > theEnd? theEnd : _size-1; // FIXME (mfh 24 Apr 2014) narrowing conversion
178  if (upper <= lower) {
179  return theEnd;
180  }
181 
182  Scalar lower_val = DV::h_view(lower);
183  Scalar upper_val = DV::h_view(upper);
184  size_t idx = (upper+lower)/2;
185  Scalar val = DV::h_view(idx);
186  if(val>upper_val) return upper;
187  if(val<lower_val) return start;
188 
189  while(upper>lower) {
190  if(comp_val>val) {
191  lower = ++idx;
192  } else {
193  upper = idx;
194  }
195  idx = (upper+lower)/2;
196  val = DV::h_view(idx);
197  }
198  return idx;
199  }
200 
201  bool is_sorted() {
202  for(int i=0;i<_size-1;i++) {
203  if(DV::h_view(i)>DV::h_view(i+1)) return false;
204  }
205  return true;
206  }
207 
208  iterator find(Scalar val) const {
209  if(_size == 0) return end();
210 
211  int upper,lower,current;
212  current = _size/2;
213  upper = _size-1;
214  lower = 0;
215 
216  if((val<DV::h_view(0)) || (val>DV::h_view(_size-1)) ) return end();
217 
218  while(upper>lower)
219  {
220  if(val>DV::h_view(current)) lower = current+1;
221  else upper = current;
222  current = (upper+lower)/2;
223  }
224 
225  if(val==DV::h_view(current)) return &DV::h_view(current);
226  else return end();
227  }
228 
229  /* Additional functions for data management */
230 
231  void device_to_host(){
232  deep_copy(DV::h_view,DV::d_view);
233  }
234  void host_to_device() const {
235  deep_copy(DV::d_view,DV::h_view);
236  }
237 
238  void on_host() {
239  DV::modified_host() = DV::modified_device() + 1;
240  }
241  void on_device() {
242  DV::modified_device() = DV::modified_host() + 1;
243  }
244 
245  void set_overallocation(float extra) {
246  _extra_storage = 1.0 + extra;
247  }
248 
249 
250 public:
251  struct set_functor {
252  typedef typename DV::t_dev::execution_space execution_space;
253  typename DV::t_dev _data;
254  Scalar _val;
255 
256  set_functor(typename DV::t_dev data, Scalar val) :
257  _data(data),_val(val) {}
258 
259  KOKKOS_INLINE_FUNCTION
260  void operator() (const int &i) const {
261  _data(i) = _val;
262  }
263  };
264 
265  struct set_functor_host {
266  typedef typename DV::t_host::execution_space execution_space;
267  typename DV::t_host _data;
268  Scalar _val;
269 
270  set_functor_host(typename DV::t_host data, Scalar val) :
271  _data(data),_val(val) {}
272 
273  KOKKOS_INLINE_FUNCTION
274  void operator() (const int &i) const {
275  _data(i) = _val;
276  }
277  };
278 
279 };
280 
281 
282 }
283 #endif
Declaration and definition of Kokkos::DualView.
std::enable_if< std::is_same< typename Kokkos::View< T, P... >::array_layout, Kokkos::LayoutLeft >::value||std::is_same< typename Kokkos::View< T, P... >::array_layout, Kokkos::LayoutRight >::value >::type resize(Kokkos::View< T, P... > &v, const size_t n0=0, const size_t n1=0, const size_t n2=0, const size_t n3=0, const size_t n4=0, const size_t n5=0, const size_t n6=0, const size_t n7=0)
Resize a view with copying old data to new data at the corresponding indices.
void parallel_for(const ExecPolicy &policy, const FunctorType &functor, const std::string &str="", typename Impl::enable_if< ! Impl::is_integral< ExecPolicy >::value >::type *=0)
Execute functor in parallel according to the execution policy.
void deep_copy(const View< DT, DP... > &dst, typename ViewTraits< DT, DP... >::const_value_type &value, typename std::enable_if< std::is_same< typename ViewTraits< DT, DP... >::specialize, void >::value >::type *=0)
Deep copy a value from Host memory into a view.