span.hpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2020-2026, 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 <cuda/std/span>
16 #include <thrust/detail/raw_pointer_cast.h>
17 #include <thrust/device_vector.h>
18 #include <thrust/host_vector.h>
19 #include <thrust/memory.h>
20 
21 #include <cstddef>
22 #include <limits>
23 #include <span>
24 #include <type_traits>
25 #include <utility>
26 
27 namespace CUDF_EXPORT cudf {
36 constexpr std::size_t dynamic_extent = std::numeric_limits<std::size_t>::max();
37  // end of group
39 namespace detail {
40 
45 template <typename T, std::size_t Extent, typename Derived>
46 class span_base {
47  static_assert(Extent == dynamic_extent, "Only dynamic extent is supported");
48 
49  public:
50  using element_type = T;
51  using value_type = std::remove_cv<T>;
52  using size_type = std::size_t;
53  using difference_type = std::ptrdiff_t;
54  using pointer = T*;
55  using iterator = T*;
56  using const_pointer = T const*;
57  using reference = T&;
59  T const&;
60 
61  static constexpr std::size_t extent = Extent;
62 
63  CUDF_HOST_DEVICE constexpr span_base() noexcept {}
70  CUDF_HOST_DEVICE constexpr span_base(pointer data, size_type size) : _data(data), _size(size) {}
71  // constexpr span_base(pointer begin, pointer end) : _data(begin), _size(end - begin) {}
72  CUDF_HOST_DEVICE constexpr span_base(span_base const&) noexcept = default;
78  CUDF_HOST_DEVICE constexpr span_base& operator=(span_base const&) noexcept = default;
79 
87  [[nodiscard]] CUDF_HOST_DEVICE constexpr iterator begin() const noexcept { return _data; }
95  [[nodiscard]] CUDF_HOST_DEVICE constexpr iterator end() const noexcept { return _data + _size; }
101  [[nodiscard]] CUDF_HOST_DEVICE constexpr pointer data() const noexcept { return _data; }
102 
108  [[nodiscard]] CUDF_HOST_DEVICE constexpr size_type size() const noexcept { return _size; }
114  [[nodiscard]] CUDF_HOST_DEVICE constexpr size_type size_bytes() const noexcept
115  {
116  return sizeof(T) * _size;
117  }
118 
124  [[nodiscard]] CUDF_HOST_DEVICE constexpr bool empty() const noexcept { return _size == 0; }
125 
132  [[nodiscard]] constexpr Derived first(size_type count) const noexcept
133  {
134  return Derived(_data, count);
135  }
136 
143  [[nodiscard]] constexpr Derived last(size_type count) const noexcept
144  {
145  return Derived(_data + _size - count, count);
146  }
147 
148  protected:
149  pointer _data{nullptr};
150  size_type _size{0};
151 };
152 
153 } // namespace detail
154 
162 // ===== host_span =================================================================================
163 
164 template <typename T>
165 struct is_host_span_supported_container : std::false_type {};
166 
167 template <typename T, typename Alloc>
169  std::vector<T, Alloc>> : std::true_type {};
170 
171 template <typename T, typename Alloc>
173  thrust::host_vector<T, Alloc>> : std::true_type {};
174 
175 template <typename T, typename Alloc>
177  std::basic_string<T, std::char_traits<T>, Alloc>> : std::true_type {};
178 
183 template <typename T, std::size_t Extent = cudf::dynamic_extent>
184 struct host_span : public cudf::detail::span_base<T, Extent, host_span<T, Extent>> {
186  using base::base;
187 
188  constexpr host_span() noexcept : base() {} // required to compile on centos
189 
199  CUDF_HOST_DEVICE constexpr host_span(T* data, std::size_t size, bool is_device_accessible)
200  : base(data, size), _is_device_accessible{is_device_accessible}
201  {
202  }
203 
206  template <typename C,
207  // Only supported containers of types convertible to T
208  std::enable_if_t<is_host_span_supported_container<C>::value &&
209  std::is_convertible_v<
210  std::remove_pointer_t<decltype(thrust::raw_pointer_cast( // NOLINT
211  std::declval<C&>().data()))> (*)[],
212  T (*)[]>>* = nullptr> // NOLINT
213  constexpr host_span(C& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
214  {
215  }
216 
219  template <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<
223  std::remove_pointer_t<decltype(thrust::raw_pointer_cast( // NOLINT
224  std::declval<C&>().data()))> (*)[],
225  T (*)[]>>* = nullptr> // NOLINT
226  constexpr host_span(C const& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
227  {
228  }
229 
230  // Copy construction to support const conversion
232  template <typename OtherT,
233  std::size_t OtherExtent,
234  std::enable_if_t<(Extent == OtherExtent || Extent == dynamic_extent) &&
235  std::is_convertible_v<OtherT (*)[], T (*)[]>, // NOLINT
236  void>* = nullptr>
237  constexpr host_span(host_span<OtherT, OtherExtent> const& other) noexcept
238  : base(other.data(), other.size()), _is_device_accessible{other.is_device_accessible()}
239  {
240  }
241  // not noexcept due to undefined behavior when idx < 0 || idx >= size
251  constexpr typename base::reference operator[](typename base::size_type idx) const
252  {
253  static_assert(sizeof(idx) >= sizeof(size_t), "index type must not be smaller than size_t");
254  return this->_data[idx];
255  }
256 
257  // not noexcept due to undefined behavior when size = 0
265  [[nodiscard]] constexpr typename base::reference front() const { return this->_data[0]; }
266  // not noexcept due to undefined behavior when size = 0
274  [[nodiscard]] constexpr typename base::reference back() const
275  {
276  return this->_data[this->_size - 1];
277  }
278 
284  [[nodiscard]] bool is_device_accessible() const { return _is_device_accessible; }
285 
293  [[nodiscard]] CUDF_HOST_DEVICE constexpr host_span subspan(
294  typename base::size_type offset, typename base::size_type count) const noexcept
295  {
296  return host_span{this->data() + offset, count, _is_device_accessible};
297  }
298 
304  [[nodiscard]] constexpr operator std::span<T>() const noexcept
305  {
306  return std::span<T>(this->data(), this->size());
307  }
308 
309  private:
310  bool _is_device_accessible{false};
311 };
312 
313 // ===== device_span ===============================================================================
314 
319 template <typename T, std::size_t Extent = cuda::std::dynamic_extent>
320 using device_span = cuda::std::span<T, Extent>; // end of group
322 
323 namespace detail {
324 
330 template <typename T, template <typename, std::size_t> typename RowType>
331 class base_2dspan {
332  public:
333  using size_type =
334  std::pair<size_t, size_t>;
335 
336  constexpr base_2dspan() noexcept = default;
343  constexpr base_2dspan(RowType<T, dynamic_extent> flat_view, size_t columns)
344  : _flat{flat_view}, _size{columns == 0 ? 0 : flat_view.size() / columns, columns}
345  {
346 #ifndef __CUDA_ARCH__
347  CUDF_EXPECTS(_size.first * _size.second == flat_view.size(), "Invalid 2D span size");
348 #endif
349  }
350 
356  [[nodiscard]] CUDF_HOST_DEVICE constexpr auto data() const noexcept { return _flat.data(); }
357 
363  [[nodiscard]] CUDF_HOST_DEVICE constexpr auto size() const noexcept { return _size; }
364 
370  [[nodiscard]] CUDF_HOST_DEVICE constexpr auto count() const noexcept { return _flat.size(); }
371 
377  [[nodiscard]] CUDF_HOST_DEVICE constexpr bool is_empty() const noexcept { return count() == 0; }
378 
388  CUDF_HOST_DEVICE constexpr RowType<T, dynamic_extent> operator[](std::size_t row) const
389  {
390  return _flat.subspan(row * _size.second, _size.second);
391  }
392 
398  [[nodiscard]] CUDF_HOST_DEVICE constexpr RowType<T, dynamic_extent> flat_view() const
399  {
400  return _flat;
401  }
402 
410  template <typename OtherT,
411  template <typename, size_t> typename OtherRowType,
412  std::enable_if_t<std::is_convertible_v<OtherRowType<OtherT, dynamic_extent>,
413  RowType<T, dynamic_extent>>,
414  void>* = nullptr>
415  constexpr base_2dspan(base_2dspan<OtherT, OtherRowType> const& other) noexcept
416  : _flat{other.flat_view()}, _size{other.size()}
417  {
418  }
419 
420  protected:
421  RowType<T, dynamic_extent> _flat;
422  size_type _size{0, 0};
423 };
424 
430 template <class T>
432 
438 template <class T>
440 
441 } // namespace detail
442 } // namespace CUDF_EXPORT cudf
Generic class for row-major 2D spans. Not compliant with STL container semantics/syntax.
Definition: span.hpp:331
std::pair< size_t, size_t > size_type
Type used to represent the dimension of the span.
Definition: span.hpp:334
constexpr CUDF_HOST_DEVICE bool is_empty() const noexcept
Checks if the span is empty.
Definition: span.hpp:377
constexpr CUDF_HOST_DEVICE auto size() const noexcept
Returns the size in the span as pair.
Definition: span.hpp:363
constexpr CUDF_HOST_DEVICE auto count() const noexcept
Returns the number of elements in the span.
Definition: span.hpp:370
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:388
constexpr CUDF_HOST_DEVICE auto data() const noexcept
Returns a pointer to the beginning of the sequence.
Definition: span.hpp:356
constexpr CUDF_HOST_DEVICE RowType< T, dynamic_extent > flat_view() const
Returns a flattened span of the 2D span.
Definition: span.hpp:398
RowType< T, dynamic_extent > _flat
flattened 2D span
Definition: span.hpp:421
constexpr base_2dspan(base_2dspan< OtherT, OtherRowType > const &other) noexcept
Construct a 2D span from another 2D span of convertible type.
Definition: span.hpp:415
C++20 std::span with reduced feature set.
Definition: span.hpp:46
std::size_t size_type
The type used for the size of the span.
Definition: span.hpp:52
constexpr CUDF_HOST_DEVICE iterator end() const noexcept
Returns an iterator to the element following the last element of the span.
Definition: span.hpp:95
constexpr Derived first(size_type count) const noexcept
Obtains a subspan consisting of the first N elements of the sequence.
Definition: span.hpp:132
T * iterator
The type of the iterator returned by begin()
Definition: span.hpp:55
constexpr CUDF_HOST_DEVICE pointer data() const noexcept
Returns a pointer to the beginning of the sequence.
Definition: span.hpp:101
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:108
constexpr Derived last(size_type count) const noexcept
Obtains a subspan consisting of the last N elements of the sequence.
Definition: span.hpp:143
std::remove_cv< T > value_type
Stored value type.
Definition: span.hpp:51
std::ptrdiff_t difference_type
std::ptrdiff_t
Definition: span.hpp:53
T * pointer
The type of the pointer returned by data()
Definition: span.hpp:54
T const * const_pointer
The type of the pointer returned by data() const.
Definition: span.hpp:56
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:70
T & reference
The type of the reference returned by operator[](size_type)
Definition: span.hpp:57
constexpr CUDF_HOST_DEVICE bool empty() const noexcept
Checks if the span is empty.
Definition: span.hpp:124
constexpr CUDF_HOST_DEVICE iterator begin() const noexcept
Returns an iterator to the first element of the span.
Definition: span.hpp:87
constexpr CUDF_HOST_DEVICE size_type size_bytes() const noexcept
Returns the size of the sequence in bytes.
Definition: span.hpp:114
T const & const_reference
The type of the reference returned by operator[](size_type) const.
Definition: span.hpp:59
T element_type
The type of the elements in the span.
Definition: span.hpp:50
#define CUDF_EXPECTS(...)
Macro for checking (pre-)conditions that throws an exception when a condition is violated.
Definition: error.hpp:143
cuda::std::span< T, Extent > device_span
Device span is an alias of cuda::std::span.
Definition: span.hpp:320
constexpr std::size_t dynamic_extent
A constant used to differentiate std::span of static and dynamic extent.
Definition: span.hpp:36
cuDF interfaces
Definition: host_udf.hpp:26
C++20 std::span with reduced feature set.
Definition: span.hpp:184
constexpr base::reference front() const
Returns a reference to the first element in the span.
Definition: span.hpp:265
constexpr base::reference operator[](typename base::size_type idx) const
Returns a reference to the idx-th element of the sequence.
Definition: span.hpp:251
constexpr host_span(C const &in)
Definition: span.hpp:226
bool is_device_accessible() const
Returns whether the data is device accessible (e.g. pinned memory)
Definition: span.hpp:284
constexpr host_span(host_span< OtherT, OtherExtent > const &other) noexcept
Definition: span.hpp:237
constexpr CUDF_HOST_DEVICE host_span(T *data, std::size_t size, bool is_device_accessible)
Constructor from pointer and size.
Definition: span.hpp:199
constexpr base::reference back() const
Returns a reference to the last element in the span.
Definition: span.hpp:274
constexpr host_span(C &in)
Definition: span.hpp:213
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:293
Type declarations for libcudf.
#define CUDF_HOST_DEVICE
Indicates that the function or method is usable on host and device.
Definition: types.hpp:21