Low-Level Abstraction of Memory Access
Vector.hpp
Go to the documentation of this file.
1 // Copyright 2021 Bernhard Manfred Gruber
2 // SPDX-License-Identifier: MPL-2.0
3 
4 #pragma once
5 
6 #include "RecordRef.hpp"
7 #include "View.hpp"
8 
9 #include <algorithm>
10 #include <stdexcept>
11 #include <string>
12 
13 namespace llama
14 {
15  // TODO(bgruber): expose blob allocator
21  template<typename Mapping>
22  struct Vector
23  {
24  static_assert(Mapping::ArrayExtents::rank == 1, "llama::Vector only supports 1D mappings");
25 
26  using ViewType = decltype(allocViewUninitialized<Mapping>());
27  using RecordDim = typename Mapping::RecordDim;
28 
29  using iterator = decltype(std::declval<ViewType>().begin());
30  using value_type = typename iterator::value_type;
31  using size_type = typename Mapping::ArrayExtents::value_type;
32 
33  Vector() = default;
34 
35  template<typename RecordRef = One<RecordDim>>
36  LLAMA_FN_HOST_ACC_INLINE explicit Vector(size_type count, const RecordRef& value = {})
37  {
38  reserve(count);
39  for(size_type i = 0; i < count; i++)
40  push_back(value);
41  }
42 
43  template<typename Iterator>
45  {
46  if constexpr(std::is_same_v<
47  typename std::iterator_traits<Iterator>::iterator_category,
48  std::random_access_iterator_tag>)
49  reserve(std::distance(first, last));
50  for(; first != last; ++first)
51  push_back(*first);
52  }
53 
54  Vector(const Vector& other) = default;
55 
57  {
58  swap(other);
59  }
60 
61  auto operator=(const Vector& other) -> Vector& = default;
62 
63  LLAMA_FN_HOST_ACC_INLINE auto operator=(Vector&& other) noexcept -> Vector&
64  {
65  swap(other);
66  return *this;
67  }
68 
69  ~Vector() = default;
70 
71  // TODO(bgruber): assign
72 
73  private:
74  LLAMA_FN_HOST_ACC_INLINE void outOfRange([[maybe_unused]] size_type i) const
75  {
76 #if __CUDA_ARCH__
77  assert(false && "Index out of range");
78 #else
79  throw std::out_of_range{"Index " + std::to_string(i) + "out of range [0:" + std::to_string(m_size) + "["};
80 #endif
81  }
82 
83  public:
84  LLAMA_FN_HOST_ACC_INLINE auto at(size_type i) -> decltype(auto)
85  {
86  if(i >= m_size)
87  outOfRange(i);
88  return m_view(i);
89  }
90 
91  LLAMA_FN_HOST_ACC_INLINE auto at(size_type i) const -> decltype(auto)
92  {
93  if(i >= m_size)
94  outOfRange(i);
95  return m_view(i);
96  }
97 
98  LLAMA_FN_HOST_ACC_INLINE auto operator[](size_type i) -> decltype(auto)
99  {
100  return m_view(i);
101  }
102 
103  LLAMA_FN_HOST_ACC_INLINE auto operator[](size_type i) const -> decltype(auto)
104  {
105  return m_view(i);
106  }
107 
108  LLAMA_FN_HOST_ACC_INLINE auto front() -> decltype(auto)
109  {
110  return m_view(0);
111  }
112 
113  LLAMA_FN_HOST_ACC_INLINE auto front() const -> decltype(auto)
114  {
115  return m_view(0);
116  }
117 
118  LLAMA_FN_HOST_ACC_INLINE auto back() -> decltype(auto)
119  {
120  return m_view(m_size - 1);
121  }
122 
123  LLAMA_FN_HOST_ACC_INLINE auto back() const -> decltype(auto)
124  {
125  return m_view(m_size - 1);
126  }
127 
128  LLAMA_FN_HOST_ACC_INLINE auto begin() -> decltype(auto)
129  {
130  return m_view.begin();
131  }
132 
133  LLAMA_FN_HOST_ACC_INLINE auto begin() const -> decltype(auto)
134  {
135  return m_view.begin();
136  }
137 
138  LLAMA_FN_HOST_ACC_INLINE auto cbegin() -> decltype(auto)
139  {
140  return std::as_const(m_view).begin();
141  }
142 
143  LLAMA_FN_HOST_ACC_INLINE auto cbegin() const -> decltype(auto)
144  {
145  return m_view.begin();
146  }
147 
148  LLAMA_FN_HOST_ACC_INLINE auto end() -> decltype(auto)
149  {
150  return m_view.begin() + m_size;
151  }
152 
153  LLAMA_FN_HOST_ACC_INLINE auto end() const -> decltype(auto)
154  {
155  return m_view.begin() + m_size;
156  }
157 
158  LLAMA_FN_HOST_ACC_INLINE auto cend() -> decltype(auto)
159  {
160  return std::as_const(m_view).begin() + m_size;
161  }
162 
163  LLAMA_FN_HOST_ACC_INLINE auto cend() const -> decltype(auto)
164  {
165  return m_view.begin() + m_size;
166  }
167 
168  LLAMA_FN_HOST_ACC_INLINE auto empty() const -> bool
169  {
170  return m_size == 0;
171  }
172 
174  {
175  return m_size;
176  }
177 
179  {
180  if(cap > capacity())
181  changeCapacity(cap);
182  }
183 
185  {
186  return m_view.extents()[0];
187  }
188 
189  // NOLINTNEXTLINE(readability-identifier-naming)
191  {
192  changeCapacity(m_size);
193  }
194 
196  {
197  m_size = 0;
198  }
199 
200  template<typename T>
202  {
203  const auto i = pos - begin();
204  reserve(m_size + 1); // might invalidate pos
205  pos = begin() + i;
206  std::copy_backward(pos, end(), end() + 1);
207  m_view[i] = std::forward<T>(t);
208  m_size++;
209  return pos;
210  }
211 
212  // TODO(bgruber): more insert overloads
213 
214  // TODO(bgruber): emplace
215 
217  {
218  std::copy(pos + 1, end(), pos);
219  m_size--;
220  return pos;
221  }
222 
223  // TODO(bgruber): more erase overloads
224 
225  // TODO(bgruber): T here is probably a RecordRef. We could also allow any struct that is storable to the
226  // view via RecordRef::store().
227  template<typename T>
228  // NOLINTNEXTLINE(readability-identifier-naming)
230  {
231  if(const auto cap = capacity(); m_size == cap)
232  reserve(std::max(cap + cap / 2, m_size + 1));
233 
234  m_view[m_size++] = std::forward<T>(t);
235  }
236 
237  // TODO(bgruber): emplace_back
238 
239  // NOLINTNEXTLINE(readability-identifier-naming)
241  {
242  m_size--;
243  }
244 
245  template<typename RecordRef = One<RecordDim>>
246  LLAMA_FN_HOST_ACC_INLINE void resize(size_type count, const RecordRef& value = {})
247  {
248  reserve(count);
249  for(size_type i = m_size; i < count; i++)
250  m_view[i] = value;
251  m_size = count;
252  }
253 
254  LLAMA_FN_HOST_ACC_INLINE friend auto operator==(const Vector& a, const Vector& b) -> bool
255  {
256  if(a.m_size != b.m_size)
257  return false;
258  return std::equal(a.begin(), a.end(), b.begin());
259  }
260 
261  LLAMA_FN_HOST_ACC_INLINE friend auto operator!=(const Vector& a, const Vector& b) -> bool
262  {
263  return !(a == b);
264  }
265 
266  LLAMA_FN_HOST_ACC_INLINE friend auto operator<(const Vector& a, const Vector& b) -> bool
267  {
268  return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
269  }
270 
271  LLAMA_FN_HOST_ACC_INLINE friend auto operator<=(const Vector& a, const Vector& b) -> bool
272  {
273  return !(b < a);
274  }
275 
276  LLAMA_FN_HOST_ACC_INLINE friend auto operator>(const Vector& a, const Vector& b) -> bool
277  {
278  return b < a;
279  }
280 
281  LLAMA_FN_HOST_ACC_INLINE friend auto operator>=(const Vector& a, const Vector& b) -> bool
282  {
283  return !(a < b);
284  }
285 
286  LLAMA_FN_HOST_ACC_INLINE friend void swap(Vector& a, Vector& b) noexcept
287  {
288  a.swap(b);
289  }
290 
291  private:
292  LLAMA_FN_HOST_ACC_INLINE void changeCapacity(size_type cap)
293  {
294  auto newView = allocViewUninitialized<Mapping>(Mapping{typename Mapping::ArrayExtents{cap}});
295  auto b = begin();
296  std::copy(begin(), b + std::min(m_size, cap), newView.begin());
297  using std::swap;
298  swap(m_view, newView); // depends on move semantic of View
299  }
300 
301  LLAMA_FN_HOST_ACC_INLINE void swap(Vector& other) noexcept
302  {
303  using std::swap;
304  swap(m_view, other.m_view); // depends on move semantic of View
305  swap(m_size, other.m_size);
306  }
307 
308  ViewType m_view = {};
309  size_type m_size = 0;
310  };
311 } // namespace llama
#define LLAMA_EXPORT
Definition: macros.hpp:192
#define LLAMA_FN_HOST_ACC_INLINE
Definition: macros.hpp:96
ArrayExtents(Args...) -> ArrayExtents< typename internal::IndexTypeFromArgs< std::size_t, Args... >::type,(Args{}, dyn)... >
void copy(const View< SrcMapping, SrcBlob > &srcView, View< DstMapping, DstBlob > &dstView, std::size_t threadId=0, std::size_t threadCount=1)
Definition: Copy.hpp:491
auto swap(RecordRef< ViewA, BoundRecordDimA, OwnViewA > &a, RecordRef< ViewB, BoundRecordDimB, OwnViewB > &b) noexcept -> std::enable_if_t< std::is_same_v< typename RecordRef< ViewA, BoundRecordDimA, OwnViewA >::AccessibleRecordDim, typename RecordRef< ViewB, BoundRecordDimB, OwnViewB >::AccessibleRecordDim >>
Definition: RecordRef.hpp:782
Vector(size_type count, const RecordRef &value={})
Definition: Vector.hpp:36
auto operator=(Vector &&other) noexcept -> Vector &
Definition: Vector.hpp:63
auto back() -> decltype(auto)
Definition: Vector.hpp:118
friend auto operator<=(const Vector &a, const Vector &b) -> bool
Definition: Vector.hpp:271
auto end() -> decltype(auto)
Definition: Vector.hpp:148
friend auto operator<(const Vector &a, const Vector &b) -> bool
Definition: Vector.hpp:266
auto at(size_type i) -> decltype(auto)
Definition: Vector.hpp:84
Vector(Iterator first, Iterator last)
Definition: Vector.hpp:44
auto back() const -> decltype(auto)
Definition: Vector.hpp:123
auto operator[](size_type i) const -> decltype(auto)
Definition: Vector.hpp:103
auto operator[](size_type i) -> decltype(auto)
Definition: Vector.hpp:98
auto erase(iterator pos) -> iterator
Definition: Vector.hpp:216
typename iterator::value_type value_type
Definition: Vector.hpp:30
auto begin() const -> decltype(auto)
Definition: Vector.hpp:133
auto cend() const -> decltype(auto)
Definition: Vector.hpp:163
auto front() const -> decltype(auto)
Definition: Vector.hpp:113
auto end() const -> decltype(auto)
Definition: Vector.hpp:153
decltype(std::declval< ViewType >().begin()) iterator
Definition: Vector.hpp:29
auto cbegin() -> decltype(auto)
Definition: Vector.hpp:138
auto empty() const -> bool
Definition: Vector.hpp:168
friend void swap(Vector &a, Vector &b) noexcept
Definition: Vector.hpp:286
void clear()
Definition: Vector.hpp:195
auto size() const -> size_type
Definition: Vector.hpp:173
auto insert(iterator pos, T &&t) -> iterator
Definition: Vector.hpp:201
auto operator=(const Vector &other) -> Vector &=default
friend auto operator>(const Vector &a, const Vector &b) -> bool
Definition: Vector.hpp:276
typename Mapping::RecordDim RecordDim
Definition: Vector.hpp:27
void push_back(T &&t)
Definition: Vector.hpp:229
~Vector()=default
friend auto operator!=(const Vector &a, const Vector &b) -> bool
Definition: Vector.hpp:261
void pop_back()
Definition: Vector.hpp:240
void resize(size_type count, const RecordRef &value={})
Definition: Vector.hpp:246
void shrink_to_fit()
Definition: Vector.hpp:190
friend auto operator==(const Vector &a, const Vector &b) -> bool
Definition: Vector.hpp:254
auto cbegin() const -> decltype(auto)
Definition: Vector.hpp:143
auto capacity() const -> size_type
Definition: Vector.hpp:184
auto cend() -> decltype(auto)
Definition: Vector.hpp:158
friend auto operator>=(const Vector &a, const Vector &b) -> bool
Definition: Vector.hpp:281
auto front() -> decltype(auto)
Definition: Vector.hpp:108
void reserve(size_type cap)
Definition: Vector.hpp:178
Vector(const Vector &other)=default
typename Mapping::ArrayExtents::value_type size_type
Definition: Vector.hpp:31
decltype(allocViewUninitialized< Mapping >()) ViewType
Definition: Vector.hpp:26
auto begin() -> decltype(auto)
Definition: Vector.hpp:128
Vector()=default
auto at(size_type i) const -> decltype(auto)
Definition: Vector.hpp:91
Vector(Vector &&other) noexcept
Definition: Vector.hpp:56