span.hpp
1 /*
2  * Copyright (c) 2020-2023, NVIDIA CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <rmm/device_buffer.hpp>
20 #include <rmm/device_uvector.hpp>
21 #include <rmm/device_vector.hpp>
22 
23 #include <thrust/detail/raw_pointer_cast.h>
24 #include <thrust/device_vector.h>
25 #include <thrust/host_vector.h>
26 #include <thrust/memory.h>
27 
28 #include <cstddef>
29 #include <limits>
30 #include <type_traits>
31 
32 namespace cudf {
33 
35 constexpr std::size_t dynamic_extent = std::numeric_limits<std::size_t>::max();
36 
37 namespace detail {
38 
43 template <typename T, std::size_t Extent, typename Derived>
44 class span_base {
45  static_assert(Extent == dynamic_extent, "Only dynamic extent is supported");
46 
47  public:
48  using element_type = T;
49  using value_type = std::remove_cv<T>;
50  using size_type = std::size_t;
51  using difference_type = std::ptrdiff_t;
52  using pointer = T*;
53  using iterator = T*;
54  using const_pointer = T const*;
55  using reference = T&;
57  T const&;
58 
59  static constexpr std::size_t extent = Extent;
60 
61  constexpr span_base() noexcept {}
68  constexpr span_base(pointer data, size_type size) : _data(data), _size(size) {}
69  // constexpr span_base(pointer begin, pointer end) : _data(begin), _size(end - begin) {}
70  constexpr span_base(span_base const&) noexcept = default;
71 
76  constexpr span_base& operator=(span_base const&) noexcept = default;
77 
78  // not noexcept due to undefined behavior when size = 0
86  constexpr reference front() const { return _data[0]; }
87  // not noexcept due to undefined behavior when size = 0
95  constexpr reference back() const { return _data[_size - 1]; }
96  // not noexcept due to undefined behavior when idx < 0 || idx >= size
106  constexpr reference operator[](size_type idx) const { return _data[idx]; }
107 
115  constexpr iterator begin() const noexcept { return _data; }
123  constexpr iterator end() const noexcept { return _data + _size; }
129  constexpr pointer data() const noexcept { return _data; }
130 
136  [[nodiscard]] constexpr size_type size() const noexcept { return _size; }
142  [[nodiscard]] constexpr size_type size_bytes() const noexcept { return sizeof(T) * _size; }
148  [[nodiscard]] constexpr bool empty() const noexcept { return _size == 0; }
149 
156  constexpr Derived first(size_type count) const noexcept { return Derived(_data, count); }
157 
164  constexpr Derived last(size_type count) const noexcept
165  {
166  return Derived(_data + _size - count, count);
167  }
168 
176  constexpr Derived subspan(size_type offset, size_type count) const noexcept
177  {
178  return Derived(_data + offset, count);
179  }
180 
181  private:
182  pointer _data{nullptr};
183  size_type _size{0};
184 };
185 
186 } // namespace detail
187 
188 // ===== host_span =================================================================================
189 
190 template <typename T>
191 struct is_host_span_supported_container : std::false_type {};
192 
193 template <typename T, typename Alloc>
195  std::vector<T, Alloc>> : std::true_type {};
196 
197 template <typename T, typename Alloc>
199  thrust::host_vector<T, Alloc>> : std::true_type {};
200 
201 template <typename T, typename Alloc>
203  std::basic_string<T, std::char_traits<T>, Alloc>> : std::true_type {};
204 
209 template <typename T, std::size_t Extent = cudf::dynamic_extent>
210 struct host_span : public cudf::detail::span_base<T, Extent, host_span<T, Extent>> {
212  using base::base;
213 
214  constexpr host_span() noexcept : base() {} // required to compile on centos
215 
218  template <
219  typename C,
220  // Only supported containers of types convertible to T
221  std::enable_if_t<is_host_span_supported_container<C>::value &&
222  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
223  std::declval<C&>().data()))> (*)[],
224  T (*)[]>>* = nullptr>
225  constexpr host_span(C& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
226  {
227  }
228 
231  template <
232  typename C,
233  // Only supported containers of types convertible to T
234  std::enable_if_t<is_host_span_supported_container<C>::value &&
235  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
236  std::declval<C&>().data()))> (*)[],
237  T (*)[]>>* = nullptr>
238  constexpr host_span(C const& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
239  {
240  }
241 
242  // Copy construction to support const conversion
244  template <typename OtherT,
245  std::size_t OtherExtent,
246  std::enable_if_t<(Extent == OtherExtent || Extent == dynamic_extent) &&
247  std::is_convertible_v<OtherT (*)[], T (*)[]>,
248  void>* = nullptr>
249  constexpr host_span(host_span<OtherT, OtherExtent> const& other) noexcept
250  : base(other.data(), other.size())
251  {
252  }
253 };
254 
255 // ===== device_span ===============================================================================
256 
257 template <typename T>
258 struct is_device_span_supported_container : std::false_type {};
259 
260 template <typename T, typename Alloc>
262  thrust::device_vector<T, Alloc>> : std::true_type {};
263 
264 template <typename T>
266  rmm::device_vector<T>> : std::true_type {};
267 
268 template <typename T>
270  rmm::device_uvector<T>> : std::true_type {};
271 
276 template <typename T, std::size_t Extent = cudf::dynamic_extent>
277 struct device_span : public cudf::detail::span_base<T, Extent, device_span<T, Extent>> {
279  using base::base;
280 
281  constexpr device_span() noexcept : base() {} // required to compile on centos
282 
285  template <
286  typename C,
287  // Only supported containers of types convertible to T
288  std::enable_if_t<is_device_span_supported_container<C>::value &&
289  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
290  std::declval<C&>().data()))> (*)[],
291  T (*)[]>>* = nullptr>
292  constexpr device_span(C& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
293  {
294  }
295 
298  template <
299  typename C,
300  // Only supported containers of types convertible to T
301  std::enable_if_t<is_device_span_supported_container<C>::value &&
302  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
303  std::declval<C&>().data()))> (*)[],
304  T (*)[]>>* = nullptr>
305  constexpr device_span(C const& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
306  {
307  }
308 
309  // Copy construction to support const conversion
311  template <typename OtherT,
312  std::size_t OtherExtent,
313  std::enable_if_t<(Extent == OtherExtent || Extent == dynamic_extent) &&
314  std::is_convertible_v<OtherT (*)[], T (*)[]>,
315  void>* = nullptr>
316  constexpr device_span(device_span<OtherT, OtherExtent> const& other) noexcept
317  : base(other.data(), other.size())
318  {
319  }
320 };
321 
322 namespace detail {
323 
329 template <typename T, template <typename, std::size_t> typename RowType>
330 class base_2dspan {
331  public:
332  using size_type =
333  std::pair<size_t, size_t>;
334 
335  constexpr base_2dspan() noexcept = default;
343  constexpr base_2dspan(T* data, size_t rows, size_t columns) noexcept
344  : _data{data}, _size{rows, columns}
345  {
346  }
354 
360  constexpr auto data() const noexcept { return _data; }
366  constexpr auto size() const noexcept { return _size; }
372  constexpr auto count() const noexcept { return size().first * size().second; }
378  [[nodiscard]] constexpr bool is_empty() const noexcept { return count() == 0; }
379 
388  static constexpr size_t flatten_index(size_t row, size_t column, size_type size) noexcept
389  {
390  return row * size.second + column;
391  }
392 
402  constexpr RowType<T, dynamic_extent> operator[](size_t row) const
403  {
404  return {this->data() + flatten_index(row, 0, this->size()), this->size().second};
405  }
406 
414  [[nodiscard]] constexpr RowType<T, dynamic_extent> front() const { return (*this)[0]; }
422  [[nodiscard]] constexpr RowType<T, dynamic_extent> back() const
423  {
424  return (*this)[size().first - 1];
425  }
426 
435  constexpr base_2dspan subspan(size_t first_row, size_t num_rows) const noexcept
436  {
437  return base_2dspan(
438  _data + flatten_index(first_row, 0, this->size()), num_rows, this->size().second);
439  }
440 
446  constexpr RowType<T, dynamic_extent> flat_view()
447  {
448  return {this->data(), this->size().first * this->size().second};
449  }
450 
458  template <typename OtherT,
459  template <typename, size_t>
460  typename OtherRowType,
461  std::enable_if_t<std::is_convertible_v<OtherRowType<OtherT, dynamic_extent>,
462  RowType<T, dynamic_extent>>,
463  void>* = nullptr>
464  constexpr base_2dspan(base_2dspan<OtherT, OtherRowType> const& other) noexcept
465  : _data{other.data()}, _size{other.size()}
466  {
467  }
468 
469  protected:
470  T* _data = nullptr;
471  size_type _size{0, 0};
472 };
473 
479 template <class T>
480 using host_2dspan = base_2dspan<T, host_span>;
481 
487 template <class T>
488 using device_2dspan = base_2dspan<T, device_span>;
489 
490 } // namespace detail
491 } // namespace cudf
cudf::device_span::base
cudf::detail::span_base< T, Extent, device_span< T, Extent > > base
Base type.
Definition: span.hpp:278
cudf::detail::span_base::last
constexpr Derived last(size_type count) const noexcept
Obtains a subspan consisting of the last N elements of the sequence.
Definition: span.hpp:164
cudf::detail::span_base< detail::dremel_device_view const, cudf::dynamic_extent, device_span< detail::dremel_device_view const, cudf::dynamic_extent > >::value_type
std::remove_cv< detail::dremel_device_view const > value_type
Stored value type.
Definition: span.hpp:49
cudf::column
A container of nullable device data as a column of elements.
Definition: column.hpp:48
cudf::detail::base_2dspan::data
constexpr auto data() const noexcept
Returns a pointer to the beginning of the sequence.
Definition: span.hpp:360
cudf::device_span::device_span
constexpr device_span(device_span< OtherT, OtherExtent > const &other) noexcept
Definition: span.hpp:316
cudf::detail::base_2dspan::_size
size_type _size
rows, columns
Definition: span.hpp:471
cudf::host_span::host_span
constexpr host_span(C const &in)
Definition: span.hpp:238
cudf::size_type
int32_t size_type
Row index type for columns and tables.
Definition: types.hpp:80
cudf::host_span::host_span
constexpr host_span(C &in)
Definition: span.hpp:225
cudf::detail::span_base::first
constexpr Derived first(size_type count) const noexcept
Obtains a subspan consisting of the first N elements of the sequence.
Definition: span.hpp:156
cudf::detail::base_2dspan
Generic class for row-major 2D spans. Not compliant with STL container semantics/syntax.
Definition: span.hpp:330
cudf::detail::span_base::subspan
constexpr Derived subspan(size_type offset, size_type count) const noexcept
Obtains a span that is a view over the count elements of this span starting at offset.
Definition: span.hpp:176
cudf::host_span
C++20 std::span with reduced feature set.
Definition: span.hpp:210
rmm
cudf::detail::span_base::empty
constexpr bool empty() const noexcept
Checks if the span is empty.
Definition: span.hpp:148
cudf::detail::base_2dspan::operator[]
constexpr RowType< T, dynamic_extent > operator[](size_t row) const
Returns a reference to the row-th element of the sequence.
Definition: span.hpp:402
cudf::detail::span_base::back
constexpr reference back() const
Returns a reference to the last element in the span.
Definition: span.hpp:95
cudf::detail::span_base
C++20 std::span with reduced feature set.
Definition: span.hpp:44
cudf::detail::span_base::end
constexpr iterator end() const noexcept
Returns an iterator to the element following the last element of the span.
Definition: span.hpp:123
cudf::detail::span_base< detail::dremel_device_view const, cudf::dynamic_extent, device_span< detail::dremel_device_view const, cudf::dynamic_extent > >::element_type
detail::dremel_device_view const element_type
The type of the elements in the span.
Definition: span.hpp:48
cudf::detail::span_base::size_bytes
constexpr size_type size_bytes() const noexcept
Returns the size of the sequence in bytes.
Definition: span.hpp:142
cudf::host_span::base
cudf::detail::span_base< T, Extent, host_span< T, Extent > > base
Base type.
Definition: span.hpp:211
cudf::detail::base_2dspan::subspan
constexpr base_2dspan subspan(size_t first_row, size_t num_rows) const noexcept
Obtains a 2D span that is a view over the num_rows rows of this span starting at first_row
Definition: span.hpp:435
cudf::device_span::device_span
constexpr device_span(C const &in)
Definition: span.hpp:305
cudf::detail::base_2dspan::base_2dspan
base_2dspan(T *data, size_type size) noexcept
Constructor a 2D span.
Definition: span.hpp:353
device_buffer.hpp
cudf::detail::span_base::data
constexpr pointer data() const noexcept
Returns a pointer to the beginning of the sequence.
Definition: span.hpp:129
cudf::detail::span_base::operator[]
constexpr reference operator[](size_type idx) const
Returns a reference to the idx-th element of the sequence.
Definition: span.hpp:106
cudf::detail::span_base< detail::dremel_device_view const, cudf::dynamic_extent, device_span< detail::dremel_device_view const, cudf::dynamic_extent > >::const_pointer
detail::dremel_device_view const const * const_pointer
The type of the pointer returned by data() const.
Definition: span.hpp:54
cudf::is_host_span_supported_container
Definition: span.hpp:191
cudf::detail::span_base< detail::dremel_device_view const, cudf::dynamic_extent, device_span< detail::dremel_device_view const, cudf::dynamic_extent > >::size_type
std::size_t size_type
The type used for the size of the span.
Definition: span.hpp:50
cudf::detail::base_2dspan::_data
T * _data
pointer to the first element
Definition: span.hpp:470
cudf::detail::span_base::extent
static constexpr std::size_t extent
The extent of the span.
Definition: span.hpp:59
cudf::detail::base_2dspan::front
constexpr RowType< T, dynamic_extent > front() const
Returns a reference to the first element in the span.
Definition: span.hpp:414
cudf
cuDF interfaces
Definition: aggregation.hpp:34
cudf::detail::span_base< detail::dremel_device_view const, cudf::dynamic_extent, device_span< detail::dremel_device_view const, cudf::dynamic_extent > >::iterator
detail::dremel_device_view const * iterator
The type of the iterator returned by begin()
Definition: span.hpp:53
cudf::detail::base_2dspan::size_type
std::pair< size_t, size_t > size_type
Type used to represent the dimension of the span.
Definition: span.hpp:333
cudf::detail::base_2dspan::base_2dspan
constexpr base_2dspan(base_2dspan< OtherT, OtherRowType > const &other) noexcept
Construct a 2D span from another 2D span of convertible type.
Definition: span.hpp:464
cudf::detail::base_2dspan::is_empty
constexpr bool is_empty() const noexcept
Checks if the span is empty.
Definition: span.hpp:378
cudf::detail::span_base< detail::dremel_device_view const, cudf::dynamic_extent, device_span< detail::dremel_device_view const, cudf::dynamic_extent > >::const_reference
detail::dremel_device_view const const & const_reference
The type of the reference returned by operator[](size_type) const.
Definition: span.hpp:57
cudf::detail::span_base< detail::dremel_device_view const, cudf::dynamic_extent, device_span< detail::dremel_device_view const, cudf::dynamic_extent > >::difference_type
std::ptrdiff_t difference_type
std::ptrdiff_t
Definition: span.hpp:51
cudf::host_span::host_span
constexpr host_span(host_span< OtherT, OtherExtent > const &other) noexcept
Definition: span.hpp:249
cudf::dynamic_extent
constexpr std::size_t dynamic_extent
A constant used to differentiate std::span of static and dynamic extent.
Definition: span.hpp:35
cudf::detail::span_base::span_base
constexpr span_base(span_base const &) noexcept=default
Copy constructor.
cudf::detail::base_2dspan::flat_view
constexpr RowType< T, dynamic_extent > flat_view()
Returns a flattened span of the 2D span.
Definition: span.hpp:446
cudf::detail::span_base::front
constexpr reference front() const
Returns a reference to the first element in the span.
Definition: span.hpp:86
cudf::detail::span_base< detail::dremel_device_view const, cudf::dynamic_extent, device_span< detail::dremel_device_view const, cudf::dynamic_extent > >::reference
detail::dremel_device_view const & reference
The type of the reference returned by operator[](size_type)
Definition: span.hpp:55
cudf::detail::base_2dspan::flatten_index
static constexpr size_t flatten_index(size_t row, size_t column, size_type size) noexcept
Returns flattened index of the element at the specified 2D position.
Definition: span.hpp:388
cudf::detail::base_2dspan::back
constexpr RowType< T, dynamic_extent > back() const
Returns a reference to the last element in the span.
Definition: span.hpp:422
cudf::detail::span_base< detail::dremel_device_view const, cudf::dynamic_extent, device_span< detail::dremel_device_view const, cudf::dynamic_extent > >::pointer
detail::dremel_device_view const * pointer
The type of the pointer returned by data()
Definition: span.hpp:52
cudf::device_span
Device version of C++20 std::span with reduced feature set.
Definition: span.hpp:277
cudf::detail::span_base::operator=
constexpr span_base & operator=(span_base const &) noexcept=default
Copy assignment operator.
cudf::detail::base_2dspan::size
constexpr auto size() const noexcept
Returns the size in the span as pair.
Definition: span.hpp:366
cudf::detail::span_base::span_base
constexpr span_base(pointer data, size_type size)
Constructs a span from a pointer and a size.
Definition: span.hpp:68
cudf::detail::base_2dspan::count
constexpr auto count() const noexcept
Returns the number of elements in the span.
Definition: span.hpp:372
cudf::detail::span_base::size
constexpr size_type size() const noexcept
Returns the number of elements in the span.
Definition: span.hpp:136
cudf::is_device_span_supported_container
Definition: span.hpp:258
cudf::device_span::device_span
constexpr device_span(C &in)
Definition: span.hpp:292
cudf::detail::span_base::begin
constexpr iterator begin() const noexcept
Returns an iterator to the first element of the span.
Definition: span.hpp:115