Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Kokkos_Vector.hpp
1 //@HEADER
2 // ************************************************************************
3 //
4 // Kokkos v. 4.0
5 // Copyright (2022) National Technology & Engineering
6 // Solutions of Sandia, LLC (NTESS).
7 //
8 // Under the terms of Contract DE-NA0003525 with NTESS,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
12 // See https://kokkos.org/LICENSE for license information.
13 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14 //
15 //@HEADER
16 
17 #ifndef KOKKOS_VECTOR_HPP
18 #define KOKKOS_VECTOR_HPP
19 #ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
20 #define KOKKOS_IMPL_PUBLIC_INCLUDE
21 #define KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_VECTOR
22 #endif
23 
24 #include <Kokkos_Macros.hpp>
25 
26 #if defined(KOKKOS_ENABLE_DEPRECATED_CODE_4)
27 #if defined(KOKKOS_ENABLE_DEPRECATION_WARNINGS)
28 namespace {
29 [[deprecated("Deprecated <Kokkos_Vector.hpp> header is included")]] int
30 emit_warning_kokkos_vector_deprecated() {
31  return 0;
32 }
33 static auto do_not_include = emit_warning_kokkos_vector_deprecated();
34 } // namespace
35 #endif
36 #else
37 #error "Deprecated <Kokkos_Vector.hpp> header is included"
38 #endif
39 
40 #include <Kokkos_Core_fwd.hpp>
41 #include <Kokkos_DualView.hpp>
42 
43 /* Drop in replacement for std::vector based on Kokkos::DualView
44  * Most functions only work on the host (it will not compile if called from
45  * device kernel)
46  *
47  */
48 namespace Kokkos {
49 
50 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
51 template <class Scalar, class Arg1Type = void>
52 class KOKKOS_DEPRECATED vector
53  : public DualView<Scalar*, LayoutLeft, Arg1Type> {
54  public:
55  using value_type = Scalar;
56  using pointer = Scalar*;
57  using const_pointer = const Scalar*;
58  using reference = Scalar&;
59  using const_reference = const Scalar&;
60  using iterator = Scalar*;
61  using const_iterator = const Scalar*;
62  using size_type = size_t;
63 
64  private:
65  size_t _size;
66  float _extra_storage;
67  using DV = DualView<Scalar*, LayoutLeft, Arg1Type>;
68 
69  public:
70 #ifdef KOKKOS_ENABLE_CUDA_UVM
71  KOKKOS_INLINE_FUNCTION reference operator()(int i) const {
72  return DV::h_view(i);
73  };
74  KOKKOS_INLINE_FUNCTION reference operator[](int i) const {
75  return DV::h_view(i);
76  };
77 #else
78  inline reference operator()(int i) const { return DV::h_view(i); };
79  inline reference operator[](int i) const { return DV::h_view(i); };
80 #endif
81 
82  /* Member functions which behave like std::vector functions */
83 
84  vector() : DV() {
85  _size = 0;
86  _extra_storage = 1.1;
87  }
88 
89  vector(int n, Scalar val = Scalar())
90  : DualView<Scalar*, LayoutLeft, Arg1Type>("Vector", size_t(n * (1.1))) {
91  _size = n;
92  _extra_storage = 1.1;
93  DV::modified_flags(0) = 1;
94 
95  assign(n, val);
96  }
97 
98  void resize(size_t n) {
99  if (n >= span()) DV::resize(size_t(n * _extra_storage));
100  _size = n;
101  }
102 
103  void resize(size_t n, const Scalar& val) { assign(n, val); }
104 
105  void assign(size_t n, const Scalar& val) {
106  /* Resize if necessary (behavior of std:vector) */
107 
108  if (n > span()) DV::resize(size_t(n * _extra_storage));
109  _size = n;
110 
111  /* Assign value either on host or on device */
112 
113  if (DV::template need_sync<typename DV::t_dev::device_type>()) {
114  set_functor_host f(DV::h_view, val);
115  parallel_for("Kokkos::vector::assign", n, f);
116  typename DV::t_host::execution_space().fence(
117  "Kokkos::vector::assign: fence after assigning values");
118  DV::template modify<typename DV::t_host::device_type>();
119  } else {
120  set_functor f(DV::d_view, val);
121  parallel_for("Kokkos::vector::assign", n, f);
122  typename DV::t_dev::execution_space().fence(
123  "Kokkos::vector::assign: fence after assigning values");
124  DV::template modify<typename DV::t_dev::device_type>();
125  }
126  }
127 
128  void reserve(size_t n) { DV::resize(size_t(n * _extra_storage)); }
129 
130  void push_back(Scalar val) {
131  DV::template sync<typename DV::t_host::device_type>();
132  DV::template modify<typename DV::t_host::device_type>();
133  if (_size == span()) {
134  size_t new_size = _size * _extra_storage;
135  if (new_size == _size) new_size++;
136  DV::resize(new_size);
137  }
138 
139  DV::h_view(_size) = val;
140  _size++;
141  }
142 
143  void pop_back() { _size--; }
144 
145  void clear() { _size = 0; }
146 
147  iterator insert(iterator it, const value_type& val) {
148  return insert(it, 1, val);
149  }
150 
151  iterator insert(iterator it, size_type count, const value_type& val) {
152  if ((size() == 0) && (it == begin())) {
153  resize(count, val);
154  DV::sync_host();
155  return begin();
156  }
157  DV::sync_host();
158  DV::modify_host();
159  if (std::less<>()(it, begin()) || std::less<>()(end(), it))
160  Kokkos::abort("Kokkos::vector::insert : invalid insert iterator");
161  if (count == 0) return it;
162  ptrdiff_t start = std::distance(begin(), it);
163  auto org_size = size();
164  resize(size() + count);
165 
166  std::copy_backward(begin() + start, begin() + org_size,
167  begin() + org_size + count);
168  std::fill_n(begin() + start, count, val);
169 
170  return begin() + start;
171  }
172 
173  private:
174  template <class T>
175  struct impl_is_input_iterator
176  : /* TODO replace this */ std::bool_constant<
177  !std::is_convertible<T, size_type>::value> {};
178 
179  public:
180  // TODO: can use detection idiom to generate better error message here later
181  template <typename InputIterator>
182  std::enable_if_t<impl_is_input_iterator<InputIterator>::value, iterator>
183  insert(iterator it, InputIterator b, InputIterator e) {
184  ptrdiff_t count = std::distance(b, e);
185 
186  DV::sync_host();
187  DV::modify_host();
188  if (std::less<>()(it, begin()) || std::less<>()(end(), it))
189  Kokkos::abort("Kokkos::vector::insert : invalid insert iterator");
190 
191  ptrdiff_t start = std::distance(begin(), it);
192  auto org_size = size();
193 
194  // Note: resize(...) invalidates it; use begin() + start instead
195  resize(size() + count);
196 
197  std::copy_backward(begin() + start, begin() + org_size,
198  begin() + org_size + count);
199  std::copy(b, e, begin() + start);
200 
201  return begin() + start;
202  }
203 
204  KOKKOS_INLINE_FUNCTION constexpr bool is_allocated() const {
205  return DV::is_allocated();
206  }
207 
208  size_type size() const { return _size; }
209  size_type max_size() const { return 2000000000; }
210  size_type span() const { return DV::span(); }
211  bool empty() const { return _size == 0; }
212 
213  pointer data() const { return DV::h_view.data(); }
214 
215  iterator begin() const { return DV::h_view.data(); }
216 
217  const_iterator cbegin() const { return DV::h_view.data(); }
218 
219  iterator end() const {
220  return _size > 0 ? DV::h_view.data() + _size : DV::h_view.data();
221  }
222 
223  const_iterator cend() const {
224  return _size > 0 ? DV::h_view.data() + _size : DV::h_view.data();
225  }
226 
227  reference front() { return DV::h_view(0); }
228 
229  reference back() { return DV::h_view(_size - 1); }
230 
231  const_reference front() const { return DV::h_view(0); }
232 
233  const_reference back() const { return DV::h_view(_size - 1); }
234 
235  /* std::algorithms which work originally with iterators, here they are
236  * implemented as member functions */
237 
238  size_t lower_bound(const size_t& start, const size_t& theEnd,
239  const Scalar& comp_val) const {
240  int lower = start; // FIXME (mfh 24 Apr 2014) narrowing conversion
241  int upper =
242  _size > theEnd
243  ? theEnd
244  : _size - 1; // FIXME (mfh 24 Apr 2014) narrowing conversion
245  if (upper <= lower) {
246  return theEnd;
247  }
248 
249  Scalar lower_val = DV::h_view(lower);
250  Scalar upper_val = DV::h_view(upper);
251  size_t idx = (upper + lower) / 2;
252  Scalar val = DV::h_view(idx);
253  if (val > upper_val) return upper;
254  if (val < lower_val) return start;
255 
256  while (upper > lower) {
257  if (comp_val > val) {
258  lower = ++idx;
259  } else {
260  upper = idx;
261  }
262  idx = (upper + lower) / 2;
263  val = DV::h_view(idx);
264  }
265  return idx;
266  }
267 
268  bool is_sorted() {
269  for (int i = 0; i < _size - 1; i++) {
270  if (DV::h_view(i) > DV::h_view(i + 1)) return false;
271  }
272  return true;
273  }
274 
275  iterator find(Scalar val) const {
276  if (_size == 0) return end();
277 
278  int upper, lower, current;
279  current = _size / 2;
280  upper = _size - 1;
281  lower = 0;
282 
283  if ((val < DV::h_view(0)) || (val > DV::h_view(_size - 1))) return end();
284 
285  while (upper > lower) {
286  if (val > DV::h_view(current))
287  lower = current + 1;
288  else
289  upper = current;
290  current = (upper + lower) / 2;
291  }
292 
293  if (val == DV::h_view(current))
294  return &DV::h_view(current);
295  else
296  return end();
297  }
298 
299  /* Additional functions for data management */
300 
301  void device_to_host() { deep_copy(DV::h_view, DV::d_view); }
302  void host_to_device() const { deep_copy(DV::d_view, DV::h_view); }
303 
304  void on_host() { DV::template modify<typename DV::t_host::device_type>(); }
305  void on_device() { DV::template modify<typename DV::t_dev::device_type>(); }
306 
307  void set_overallocation(float extra) { _extra_storage = 1.0 + extra; }
308 
309  public:
310  struct set_functor {
311  using execution_space = typename DV::t_dev::execution_space;
312  typename DV::t_dev _data;
313  Scalar _val;
314 
315  set_functor(typename DV::t_dev data, Scalar val) : _data(data), _val(val) {}
316 
317  KOKKOS_INLINE_FUNCTION
318  void operator()(const int& i) const { _data(i) = _val; }
319  };
320 
321  struct set_functor_host {
322  using execution_space = typename DV::t_host::execution_space;
323  typename DV::t_host _data;
324  Scalar _val;
325 
326  set_functor_host(typename DV::t_host data, Scalar val)
327  : _data(data), _val(val) {}
328 
329  KOKKOS_INLINE_FUNCTION
330  void operator()(const int& i) const { _data(i) = _val; }
331  };
332 };
333 #endif
334 
335 } // namespace Kokkos
336 #ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_VECTOR
337 #undef KOKKOS_IMPL_PUBLIC_INCLUDE
338 #undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_VECTOR
339 #endif
340 #endif
Declaration and definition of Kokkos::DualView.