span.hpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2020-2025, NVIDIA CORPORATION.
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #pragma once
7 
8 #include <cudf/types.hpp>
9 #include <cudf/utilities/export.hpp>
10 
11 #include <rmm/device_buffer.hpp>
12 #include <rmm/device_uvector.hpp>
13 #include <rmm/device_vector.hpp>
14 
15 #include <thrust/detail/raw_pointer_cast.h>
16 #include <thrust/device_vector.h>
17 #include <thrust/host_vector.h>
18 #include <thrust/memory.h>
19 
20 #include <cstddef>
21 #include <limits>
22 #include <type_traits>
23 #include <utility>
24 
25 namespace CUDF_EXPORT cudf {
34 constexpr std::size_t dynamic_extent = std::numeric_limits<std::size_t>::max();
35  // end of group
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  CUDF_HOST_DEVICE constexpr span_base() noexcept {}
68  CUDF_HOST_DEVICE 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  CUDF_HOST_DEVICE constexpr span_base(span_base const&) noexcept = default;
76  CUDF_HOST_DEVICE constexpr span_base& operator=(span_base const&) noexcept = default;
77 
85  [[nodiscard]] CUDF_HOST_DEVICE constexpr iterator begin() const noexcept { return _data; }
93  [[nodiscard]] CUDF_HOST_DEVICE constexpr iterator end() const noexcept { return _data + _size; }
99  [[nodiscard]] CUDF_HOST_DEVICE constexpr pointer data() const noexcept { return _data; }
100 
106  [[nodiscard]] CUDF_HOST_DEVICE constexpr size_type size() const noexcept { return _size; }
112  [[nodiscard]] CUDF_HOST_DEVICE constexpr size_type size_bytes() const noexcept
113  {
114  return sizeof(T) * _size;
115  }
116 
122  [[nodiscard]] CUDF_HOST_DEVICE constexpr bool empty() const noexcept { return _size == 0; }
123 
130  [[nodiscard]] constexpr Derived first(size_type count) const noexcept
131  {
132  return Derived(_data, count);
133  }
134 
141  [[nodiscard]] constexpr Derived last(size_type count) const noexcept
142  {
143  return Derived(_data + _size - count, count);
144  }
145 
146  protected:
147  pointer _data{nullptr};
148  size_type _size{0};
149 };
150 
151 } // namespace detail
152 
160 // ===== host_span =================================================================================
161 
162 template <typename T>
163 struct is_host_span_supported_container : std::false_type {};
164 
165 template <typename T, typename Alloc>
167  std::vector<T, Alloc>> : std::true_type {};
168 
169 template <typename T, typename Alloc>
171  thrust::host_vector<T, Alloc>> : std::true_type {};
172 
173 template <typename T, typename Alloc>
175  std::basic_string<T, std::char_traits<T>, Alloc>> : std::true_type {};
176 
181 template <typename T, std::size_t Extent = cudf::dynamic_extent>
182 struct host_span : public cudf::detail::span_base<T, Extent, host_span<T, Extent>> {
184  using base::base;
185 
186  constexpr host_span() noexcept : base() {} // required to compile on centos
187 
197  CUDF_HOST_DEVICE constexpr host_span(T* data, std::size_t size, bool is_device_accessible)
198  : base(data, size), _is_device_accessible{is_device_accessible}
199  {
200  }
201 
204  template <typename C,
205  // Only supported containers of types convertible to T
206  std::enable_if_t<is_host_span_supported_container<C>::value &&
207  std::is_convertible_v<
208  std::remove_pointer_t<decltype(thrust::raw_pointer_cast( // NOLINT
209  std::declval<C&>().data()))> (*)[],
210  T (*)[]>>* = nullptr> // NOLINT
211  constexpr host_span(C& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
212  {
213  }
214 
217  template <typename C,
218  // Only supported containers of types convertible to T
219  std::enable_if_t<is_host_span_supported_container<C>::value &&
220  std::is_convertible_v<
221  std::remove_pointer_t<decltype(thrust::raw_pointer_cast( // NOLINT
222  std::declval<C&>().data()))> (*)[],
223  T (*)[]>>* = nullptr> // NOLINT
224  constexpr host_span(C const& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
225  {
226  }
227 
228  // Copy construction to support const conversion
230  template <typename OtherT,
231  std::size_t OtherExtent,
232  std::enable_if_t<(Extent == OtherExtent || Extent == dynamic_extent) &&
233  std::is_convertible_v<OtherT (*)[], T (*)[]>, // NOLINT
234  void>* = nullptr>
235  constexpr host_span(host_span<OtherT, OtherExtent> const& other) noexcept
236  : base(other.data(), other.size()), _is_device_accessible{other.is_device_accessible()}
237  {
238  }
239  // not noexcept due to undefined behavior when idx < 0 || idx >= size
249  constexpr typename base::reference operator[](typename base::size_type idx) const
250  {
251  static_assert(sizeof(idx) >= sizeof(size_t), "index type must not be smaller than size_t");
252  return this->_data[idx];
253  }
254 
255  // not noexcept due to undefined behavior when size = 0
263  [[nodiscard]] constexpr typename base::reference front() const { return this->_data[0]; }
264  // not noexcept due to undefined behavior when size = 0
272  [[nodiscard]] constexpr typename base::reference back() const
273  {
274  return this->_data[this->_size - 1];
275  }
276 
282  [[nodiscard]] bool is_device_accessible() const { return _is_device_accessible; }
283 
291  [[nodiscard]] CUDF_HOST_DEVICE constexpr host_span subspan(
292  typename base::size_type offset, typename base::size_type count) const noexcept
293  {
294  return host_span{this->data() + offset, count, _is_device_accessible};
295  }
296 
297  private:
298  bool _is_device_accessible{false};
299 };
300 
301 // ===== device_span ===============================================================================
302 
303 template <typename T>
304 struct is_device_span_supported_container : std::false_type {};
305 
306 template <typename T, typename Alloc>
308  thrust::device_vector<T, Alloc>> : std::true_type {};
309 
310 template <typename T>
312  rmm::device_vector<T>> : std::true_type {};
313 
314 template <typename T>
316  rmm::device_uvector<T>> : std::true_type {};
317 
322 template <typename T, std::size_t Extent = cudf::dynamic_extent>
323 struct device_span : public cudf::detail::span_base<T, Extent, device_span<T, Extent>> {
325  using base::base;
326 
327  CUDF_HOST_DEVICE constexpr device_span() noexcept : base() {} // required to compile on centos
328 
331  template <typename C,
332  // Only supported containers of types convertible to T
333  std::enable_if_t<is_device_span_supported_container<C>::value &&
334  std::is_convertible_v<
335  std::remove_pointer_t<decltype(thrust::raw_pointer_cast( // NOLINT
336  std::declval<C&>().data()))> (*)[],
337  T (*)[]>>* = nullptr> // NOLINT
338  constexpr device_span(C& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
339  {
340  }
341 
344  template <typename C,
345  // Only supported containers of types convertible to T
346  std::enable_if_t<is_device_span_supported_container<C>::value &&
347  std::is_convertible_v<
348  std::remove_pointer_t<decltype(thrust::raw_pointer_cast( // NOLINT
349  std::declval<C&>().data()))> (*)[],
350  T (*)[]>>* = nullptr> // NOLINT
351  constexpr device_span(C const& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
352  {
353  }
354 
355  // Copy construction to support const conversion
357  template <typename OtherT,
358  std::size_t OtherExtent,
359  std::enable_if_t<(Extent == OtherExtent || Extent == dynamic_extent) &&
360  std::is_convertible_v<OtherT (*)[], T (*)[]>, // NOLINT
361  void>* = nullptr>
363  : base(other.data(), other.size())
364  {
365  }
366 
367  // not noexcept due to undefined behavior when idx < 0 || idx >= size
377  __device__ constexpr typename base::reference operator[](typename base::size_type idx) const
378  {
379  static_assert(sizeof(idx) >= sizeof(size_t), "index type must not be smaller than size_t");
380  return this->_data[idx];
381  }
382 
383  // not noexcept due to undefined behavior when size = 0
391  [[nodiscard]] __device__ constexpr typename base::reference front() const
392  {
393  return this->_data[0];
394  }
395  // not noexcept due to undefined behavior when size = 0
403  [[nodiscard]] __device__ constexpr typename base::reference back() const
404  {
405  return this->_data[this->_size - 1];
406  }
407 
415  [[nodiscard]] CUDF_HOST_DEVICE constexpr device_span subspan(
416  typename base::size_type offset, typename base::size_type count) const noexcept
417  {
418  return device_span{this->data() + offset, count};
419  }
420 }; // end of group
422 
423 namespace detail {
424 
430 template <typename T, template <typename, std::size_t> typename RowType>
431 class base_2dspan {
432  public:
433  using size_type =
434  std::pair<size_t, size_t>;
435 
436  constexpr base_2dspan() noexcept = default;
443  constexpr base_2dspan(RowType<T, dynamic_extent> flat_view, size_t columns)
444  : _flat{flat_view}, _size{columns == 0 ? 0 : flat_view.size() / columns, columns}
445  {
446 #ifndef __CUDA_ARCH__
447  CUDF_EXPECTS(_size.first * _size.second == flat_view.size(), "Invalid 2D span size");
448 #endif
449  }
450 
456  [[nodiscard]] CUDF_HOST_DEVICE constexpr auto data() const noexcept { return _flat.data(); }
457 
463  [[nodiscard]] CUDF_HOST_DEVICE constexpr auto size() const noexcept { return _size; }
464 
470  [[nodiscard]] CUDF_HOST_DEVICE constexpr auto count() const noexcept { return _flat.size(); }
471 
477  [[nodiscard]] CUDF_HOST_DEVICE constexpr bool is_empty() const noexcept { return count() == 0; }
478 
488  CUDF_HOST_DEVICE constexpr RowType<T, dynamic_extent> operator[](std::size_t row) const
489  {
490  return _flat.subspan(row * _size.second, _size.second);
491  }
492 
498  [[nodiscard]] CUDF_HOST_DEVICE constexpr RowType<T, dynamic_extent> flat_view() const
499  {
500  return _flat;
501  }
502 
510  template <typename OtherT,
511  template <typename, size_t> typename OtherRowType,
512  std::enable_if_t<std::is_convertible_v<OtherRowType<OtherT, dynamic_extent>,
513  RowType<T, dynamic_extent>>,
514  void>* = nullptr>
515  constexpr base_2dspan(base_2dspan<OtherT, OtherRowType> const& other) noexcept
516  : _flat{other.flat_view()}, _size{other.size()}
517  {
518  }
519 
520  protected:
521  RowType<T, dynamic_extent> _flat;
522  size_type _size{0, 0};
523 };
524 
530 template <class T>
532 
538 template <class T>
540 
541 } // namespace detail
542 } // namespace CUDF_EXPORT cudf
Generic class for row-major 2D spans. Not compliant with STL container semantics/syntax.
Definition: span.hpp:431
std::pair< size_t, size_t > size_type
Type used to represent the dimension of the span.
Definition: span.hpp:434
constexpr CUDF_HOST_DEVICE bool is_empty() const noexcept
Checks if the span is empty.
Definition: span.hpp:477
constexpr CUDF_HOST_DEVICE auto size() const noexcept
Returns the size in the span as pair.
Definition: span.hpp:463
constexpr CUDF_HOST_DEVICE auto count() const noexcept
Returns the number of elements in the span.
Definition: span.hpp:470
constexpr CUDF_HOST_DEVICE RowType< T, dynamic_extent > operator[](std::size_t row) const
Returns a reference to the row-th element of the sequence.
Definition: span.hpp:488
constexpr CUDF_HOST_DEVICE auto data() const noexcept
Returns a pointer to the beginning of the sequence.
Definition: span.hpp:456
constexpr CUDF_HOST_DEVICE RowType< T, dynamic_extent > flat_view() const
Returns a flattened span of the 2D span.
Definition: span.hpp:498
RowType< T, dynamic_extent > _flat
flattened 2D span
Definition: span.hpp:521
constexpr base_2dspan(base_2dspan< OtherT, OtherRowType > const &other) noexcept
Construct a 2D span from another 2D span of convertible type.
Definition: span.hpp:515
C++20 std::span with reduced feature set.
Definition: span.hpp:44
std::size_t size_type
The type used for the size of the span.
Definition: span.hpp:50
constexpr CUDF_HOST_DEVICE iterator end() const noexcept
Returns an iterator to the element following the last element of the span.
Definition: span.hpp:93
constexpr Derived first(size_type count) const noexcept
Obtains a subspan consisting of the first N elements of the sequence.
Definition: span.hpp:130
T * iterator
The type of the iterator returned by begin()
Definition: span.hpp:53
constexpr CUDF_HOST_DEVICE pointer data() const noexcept
Returns a pointer to the beginning of the sequence.
Definition: span.hpp:99
constexpr CUDF_HOST_DEVICE span_base(span_base const &) noexcept=default
Copy constructor.
constexpr CUDF_HOST_DEVICE size_type size() const noexcept
Returns the number of elements in the span.
Definition: span.hpp:106
constexpr Derived last(size_type count) const noexcept
Obtains a subspan consisting of the last N elements of the sequence.
Definition: span.hpp:141
std::remove_cv< T > value_type
Stored value type.
Definition: span.hpp:49
std::ptrdiff_t difference_type
std::ptrdiff_t
Definition: span.hpp:51
T * pointer
The type of the pointer returned by data()
Definition: span.hpp:52
T const * const_pointer
The type of the pointer returned by data() const.
Definition: span.hpp:54
constexpr CUDF_HOST_DEVICE span_base & operator=(span_base const &) noexcept=default
Copy assignment operator.
constexpr CUDF_HOST_DEVICE span_base(pointer data, size_type size)
Constructs a span from a pointer and a size.
Definition: span.hpp:68
T & reference
The type of the reference returned by operator[](size_type)
Definition: span.hpp:55
constexpr CUDF_HOST_DEVICE bool empty() const noexcept
Checks if the span is empty.
Definition: span.hpp:122
constexpr CUDF_HOST_DEVICE iterator begin() const noexcept
Returns an iterator to the first element of the span.
Definition: span.hpp:85
constexpr CUDF_HOST_DEVICE size_type size_bytes() const noexcept
Returns the size of the sequence in bytes.
Definition: span.hpp:112
T const & const_reference
The type of the reference returned by operator[](size_type) const.
Definition: span.hpp:57
T element_type
The type of the elements in the span.
Definition: span.hpp:48
thrust::device_vector< T, rmm::mr::thrust_allocator< T > > device_vector
#define CUDF_EXPECTS(...)
Macro for checking (pre-)conditions that throws an exception when a condition is violated.
Definition: error.hpp:143
constexpr std::size_t dynamic_extent
A constant used to differentiate std::span of static and dynamic extent.
Definition: span.hpp:34
cuDF interfaces
Definition: host_udf.hpp:26
Device version of C++20 std::span with reduced feature set.
Definition: span.hpp:323
constexpr base::reference back() const
Returns a reference to the last element in the span.
Definition: span.hpp:403
constexpr CUDF_HOST_DEVICE device_span(device_span< OtherT, OtherExtent > const &other) noexcept
Definition: span.hpp:362
constexpr base::reference front() const
Returns a reference to the first element in the span.
Definition: span.hpp:391
constexpr CUDF_HOST_DEVICE device_span subspan(typename base::size_type offset, typename base::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:415
constexpr device_span(C &in)
Definition: span.hpp:338
constexpr device_span(C const &in)
Definition: span.hpp:351
constexpr base::reference operator[](typename base::size_type idx) const
Returns a reference to the idx-th element of the sequence.
Definition: span.hpp:377
C++20 std::span with reduced feature set.
Definition: span.hpp:182
constexpr base::reference front() const
Returns a reference to the first element in the span.
Definition: span.hpp:263
constexpr base::reference operator[](typename base::size_type idx) const
Returns a reference to the idx-th element of the sequence.
Definition: span.hpp:249
constexpr host_span(C const &in)
Definition: span.hpp:224
bool is_device_accessible() const
Returns whether the data is device accessible (e.g. pinned memory)
Definition: span.hpp:282
constexpr host_span(host_span< OtherT, OtherExtent > const &other) noexcept
Definition: span.hpp:235
constexpr CUDF_HOST_DEVICE host_span(T *data, std::size_t size, bool is_device_accessible)
Constructor from pointer and size.
Definition: span.hpp:197
constexpr base::reference back() const
Returns a reference to the last element in the span.
Definition: span.hpp:272
constexpr host_span(C &in)
Definition: span.hpp:211
constexpr CUDF_HOST_DEVICE host_span subspan(typename base::size_type offset, typename base::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:291
Type declarations for libcudf.
#define CUDF_HOST_DEVICE
Indicates that the function or method is usable on host and device.
Definition: types.hpp:21