span.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020-2024, 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 <cudf/detail/utilities/host_vector.hpp>
20 #include <cudf/utilities/export.hpp>
21 
22 #include <rmm/device_buffer.hpp>
23 #include <rmm/device_uvector.hpp>
24 #include <rmm/device_vector.hpp>
25 
26 #include <thrust/detail/raw_pointer_cast.h>
27 #include <thrust/device_vector.h>
28 #include <thrust/host_vector.h>
29 #include <thrust/memory.h>
30 
31 #include <cstddef>
32 #include <limits>
33 #include <type_traits>
34 #include <utility>
35 
36 namespace CUDF_EXPORT cudf {
45 constexpr std::size_t dynamic_extent = std::numeric_limits<std::size_t>::max();
46  // end of group
48 namespace detail {
49 
54 template <typename T, std::size_t Extent, typename Derived>
55 class span_base {
56  static_assert(Extent == dynamic_extent, "Only dynamic extent is supported");
57 
58  public:
59  using element_type = T;
60  using value_type = std::remove_cv<T>;
61  using size_type = std::size_t;
62  using difference_type = std::ptrdiff_t;
63  using pointer = T*;
64  using iterator = T*;
65  using const_pointer = T const*;
66  using reference = T&;
68  T const&;
69 
70  static constexpr std::size_t extent = Extent;
71 
72  constexpr span_base() noexcept {}
79  constexpr span_base(pointer data, size_type size) : _data(data), _size(size) {}
80  // constexpr span_base(pointer begin, pointer end) : _data(begin), _size(end - begin) {}
81  constexpr span_base(span_base const&) noexcept = default;
87  constexpr span_base& operator=(span_base const&) noexcept = default;
88 
89  // not noexcept due to undefined behavior when size = 0
97  [[nodiscard]] constexpr reference front() const { return _data[0]; }
98  // not noexcept due to undefined behavior when size = 0
106  [[nodiscard]] constexpr reference back() const { return _data[_size - 1]; }
107  // not noexcept due to undefined behavior when idx < 0 || idx >= size
117  constexpr reference operator[](size_type idx) const { return _data[idx]; }
118 
126  [[nodiscard]] constexpr iterator begin() const noexcept { return _data; }
134  [[nodiscard]] constexpr iterator end() const noexcept { return _data + _size; }
140  [[nodiscard]] constexpr pointer data() const noexcept { return _data; }
141 
147  [[nodiscard]] constexpr size_type size() const noexcept { return _size; }
153  [[nodiscard]] constexpr size_type size_bytes() const noexcept { return sizeof(T) * _size; }
159  [[nodiscard]] constexpr bool empty() const noexcept { return _size == 0; }
160 
167  [[nodiscard]] constexpr Derived first(size_type count) const noexcept
168  {
169  return Derived(_data, count);
170  }
171 
178  [[nodiscard]] constexpr Derived last(size_type count) const noexcept
179  {
180  return Derived(_data + _size - count, count);
181  }
182 
183  private:
184  pointer _data{nullptr};
185  size_type _size{0};
186 };
187 
188 } // namespace detail
189 
197 // ===== host_span =================================================================================
198 
199 template <typename T>
200 struct is_host_span_supported_container : std::false_type {};
201 
202 template <typename T, typename Alloc>
204  std::vector<T, Alloc>> : std::true_type {};
205 
206 template <typename T, typename Alloc>
208  thrust::host_vector<T, Alloc>> : std::true_type {};
209 
210 template <typename T, typename Alloc>
212  std::basic_string<T, std::char_traits<T>, Alloc>> : std::true_type {};
213 
218 template <typename T, std::size_t Extent = cudf::dynamic_extent>
219 struct host_span : public cudf::detail::span_base<T, Extent, host_span<T, Extent>> {
221  using base::base;
222 
223  constexpr host_span() noexcept : base() {} // required to compile on centos
224 
229  constexpr host_span(T* data, std::size_t size, bool is_device_accessible)
230  : base(data, size), _is_device_accessible{is_device_accessible}
231  {
232  }
233 
236  template <typename C,
237  // Only supported containers of types convertible to T
238  std::enable_if_t<is_host_span_supported_container<C>::value &&
239  std::is_convertible_v<
240  std::remove_pointer_t<decltype(thrust::raw_pointer_cast( // NOLINT
241  std::declval<C&>().data()))> (*)[],
242  T (*)[]>>* = nullptr> // NOLINT
243  constexpr host_span(C& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
244  {
245  }
246 
249  template <typename C,
250  // Only supported containers of types convertible to T
251  std::enable_if_t<is_host_span_supported_container<C>::value &&
252  std::is_convertible_v<
253  std::remove_pointer_t<decltype(thrust::raw_pointer_cast( // NOLINT
254  std::declval<C&>().data()))> (*)[],
255  T (*)[]>>* = nullptr> // NOLINT
256  constexpr host_span(C const& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
257  {
258  }
259 
262  template <typename OtherT,
263  // Only supported containers of types convertible to T
264  std::enable_if_t<std::is_convertible_v<OtherT (*)[], T (*)[]>>* = nullptr> // NOLINT
265  constexpr host_span(cudf::detail::host_vector<OtherT>& in)
266  : base(in.data(), in.size()), _is_device_accessible{in.get_allocator().is_device_accessible()}
267  {
268  }
269 
272  template <typename OtherT,
273  // Only supported containers of types convertible to T
274  std::enable_if_t<std::is_convertible_v<OtherT (*)[], T (*)[]>>* = nullptr> // NOLINT
275  constexpr host_span(cudf::detail::host_vector<OtherT> const& in)
276  : base(in.data(), in.size()), _is_device_accessible{in.get_allocator().is_device_accessible()}
277  {
278  }
279 
280  // Copy construction to support const conversion
282  template <typename OtherT,
283  std::size_t OtherExtent,
284  std::enable_if_t<(Extent == OtherExtent || Extent == dynamic_extent) &&
285  std::is_convertible_v<OtherT (*)[], T (*)[]>, // NOLINT
286  void>* = nullptr>
287  constexpr host_span(host_span<OtherT, OtherExtent> const& other) noexcept
288  : base(other.data(), other.size()), _is_device_accessible{other.is_device_accessible()}
289  {
290  }
291 
297  [[nodiscard]] bool is_device_accessible() const { return _is_device_accessible; }
298 
306  [[nodiscard]] constexpr host_span subspan(typename base::size_type offset,
307  typename base::size_type count) const noexcept
308  {
309  return host_span{this->data() + offset, count, _is_device_accessible};
310  }
311 
312  private:
313  bool _is_device_accessible{false};
314 };
315 
316 // ===== device_span ===============================================================================
317 
318 template <typename T>
319 struct is_device_span_supported_container : std::false_type {};
320 
321 template <typename T, typename Alloc>
323  thrust::device_vector<T, Alloc>> : std::true_type {};
324 
325 template <typename T>
327  rmm::device_vector<T>> : std::true_type {};
328 
329 template <typename T>
331  rmm::device_uvector<T>> : std::true_type {};
332 
337 template <typename T, std::size_t Extent = cudf::dynamic_extent>
338 struct device_span : public cudf::detail::span_base<T, Extent, device_span<T, Extent>> {
340  using base::base;
341 
342  constexpr device_span() noexcept : base() {} // required to compile on centos
343 
346  template <typename C,
347  // Only supported containers of types convertible to T
348  std::enable_if_t<is_device_span_supported_container<C>::value &&
349  std::is_convertible_v<
350  std::remove_pointer_t<decltype(thrust::raw_pointer_cast( // NOLINT
351  std::declval<C&>().data()))> (*)[],
352  T (*)[]>>* = nullptr> // NOLINT
353  constexpr device_span(C& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
354  {
355  }
356 
359  template <typename C,
360  // Only supported containers of types convertible to T
361  std::enable_if_t<is_device_span_supported_container<C>::value &&
362  std::is_convertible_v<
363  std::remove_pointer_t<decltype(thrust::raw_pointer_cast( // NOLINT
364  std::declval<C&>().data()))> (*)[],
365  T (*)[]>>* = nullptr> // NOLINT
366  constexpr device_span(C const& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
367  {
368  }
369 
370  // Copy construction to support const conversion
372  template <typename OtherT,
373  std::size_t OtherExtent,
374  std::enable_if_t<(Extent == OtherExtent || Extent == dynamic_extent) &&
375  std::is_convertible_v<OtherT (*)[], T (*)[]>, // NOLINT
376  void>* = nullptr>
377  constexpr device_span(device_span<OtherT, OtherExtent> const& other) noexcept
378  : base(other.data(), other.size())
379  {
380  }
381 
389  [[nodiscard]] constexpr device_span subspan(typename base::size_type offset,
390  typename base::size_type count) const noexcept
391  {
392  return device_span{this->data() + offset, count};
393  }
394 }; // end of group
396 
397 namespace detail {
398 
404 template <typename T, template <typename, std::size_t> typename RowType>
405 class base_2dspan {
406  public:
407  using size_type =
408  std::pair<size_t, size_t>;
409 
410  constexpr base_2dspan() noexcept = default;
417  constexpr base_2dspan(RowType<T, dynamic_extent> flat_view, size_t columns)
418  : _flat{flat_view}, _size{columns == 0 ? 0 : flat_view.size() / columns, columns}
419  {
420  CUDF_EXPECTS(_size.first * _size.second == flat_view.size(), "Invalid 2D span size");
421  }
422 
428  [[nodiscard]] constexpr auto data() const noexcept { return _flat.data(); }
429 
435  [[nodiscard]] constexpr auto size() const noexcept { return _size; }
436 
442  [[nodiscard]] constexpr auto count() const noexcept { return _flat.size(); }
443 
449  [[nodiscard]] constexpr bool is_empty() const noexcept { return count() == 0; }
450 
460  constexpr RowType<T, dynamic_extent> operator[](size_t row) const
461  {
462  return _flat.subspan(row * _size.second, _size.second);
463  }
464 
470  [[nodiscard]] constexpr RowType<T, dynamic_extent> flat_view() const { return _flat; }
471 
479  template <typename OtherT,
480  template <typename, size_t>
481  typename OtherRowType,
482  std::enable_if_t<std::is_convertible_v<OtherRowType<OtherT, dynamic_extent>,
483  RowType<T, dynamic_extent>>,
484  void>* = nullptr>
485  constexpr base_2dspan(base_2dspan<OtherT, OtherRowType> const& other) noexcept
486  : _flat{other.flat_view()}, _size{other.size()}
487  {
488  }
489 
490  protected:
491  RowType<T, dynamic_extent> _flat;
492  size_type _size{0, 0};
493 };
494 
500 template <class T>
502 
508 template <class T>
510 
511 } // namespace detail
512 } // namespace CUDF_EXPORT cudf
Generic class for row-major 2D spans. Not compliant with STL container semantics/syntax.
Definition: span.hpp:405
std::pair< size_t, size_t > size_type
Type used to represent the dimension of the span.
Definition: span.hpp:408
constexpr auto count() const noexcept
Returns the number of elements in the span.
Definition: span.hpp:442
constexpr RowType< T, dynamic_extent > flat_view() const
Returns a flattened span of the 2D span.
Definition: span.hpp:470
constexpr bool is_empty() const noexcept
Checks if the span is empty.
Definition: span.hpp:449
constexpr auto data() const noexcept
Returns a pointer to the beginning of the sequence.
Definition: span.hpp:428
constexpr RowType< T, dynamic_extent > operator[](size_t row) const
Returns a reference to the row-th element of the sequence.
Definition: span.hpp:460
constexpr auto size() const noexcept
Returns the size in the span as pair.
Definition: span.hpp:435
RowType< T, dynamic_extent > _flat
flattened 2D span
Definition: span.hpp:491
constexpr base_2dspan(base_2dspan< OtherT, OtherRowType > const &other) noexcept
Construct a 2D span from another 2D span of convertible type.
Definition: span.hpp:485
C++20 std::span with reduced feature set.
Definition: span.hpp:55
constexpr iterator end() const noexcept
Returns an iterator to the element following the last element of the span.
Definition: span.hpp:134
std::size_t size_type
The type used for the size of the span.
Definition: span.hpp:61
constexpr bool empty() const noexcept
Checks if the span is empty.
Definition: span.hpp:159
constexpr reference operator[](size_type idx) const
Returns a reference to the idx-th element of the sequence.
Definition: span.hpp:117
constexpr reference back() const
Returns a reference to the last element in the span.
Definition: span.hpp:106
constexpr Derived first(size_type count) const noexcept
Obtains a subspan consisting of the first N elements of the sequence.
Definition: span.hpp:167
T * iterator
The type of the iterator returned by begin()
Definition: span.hpp:64
constexpr size_type size_bytes() const noexcept
Returns the size of the sequence in bytes.
Definition: span.hpp:153
constexpr span_base(pointer data, size_type size)
Constructs a span from a pointer and a size.
Definition: span.hpp:79
constexpr pointer data() const noexcept
Returns a pointer to the beginning of the sequence.
Definition: span.hpp:140
constexpr span_base(span_base const &) noexcept=default
Copy constructor.
constexpr Derived last(size_type count) const noexcept
Obtains a subspan consisting of the last N elements of the sequence.
Definition: span.hpp:178
std::remove_cv< T > value_type
Stored value type.
Definition: span.hpp:60
std::ptrdiff_t difference_type
std::ptrdiff_t
Definition: span.hpp:62
T * pointer
The type of the pointer returned by data()
Definition: span.hpp:63
T const * const_pointer
The type of the pointer returned by data() const.
Definition: span.hpp:65
T & reference
The type of the reference returned by operator[](size_type)
Definition: span.hpp:66
constexpr iterator begin() const noexcept
Returns an iterator to the first element of the span.
Definition: span.hpp:126
constexpr span_base & operator=(span_base const &) noexcept=default
Copy assignment operator.
constexpr reference front() const
Returns a reference to the first element in the span.
Definition: span.hpp:97
constexpr size_type size() const noexcept
Returns the number of elements in the span.
Definition: span.hpp:147
T const & const_reference
The type of the reference returned by operator[](size_type) const.
Definition: span.hpp:68
T element_type
The type of the elements in the span.
Definition: span.hpp:59
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:178
constexpr std::size_t dynamic_extent
A constant used to differentiate std::span of static and dynamic extent.
Definition: span.hpp:45
int32_t size_type
Row index type for columns and tables.
Definition: types.hpp:95
cuDF interfaces
Definition: aggregation.hpp:35
Device version of C++20 std::span with reduced feature set.
Definition: span.hpp:338
constexpr device_span(device_span< OtherT, OtherExtent > const &other) noexcept
Definition: span.hpp:377
constexpr device_span(C &in)
Definition: span.hpp:353
constexpr 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:389
constexpr device_span(C const &in)
Definition: span.hpp:366
C++20 std::span with reduced feature set.
Definition: span.hpp:219
constexpr host_span(cudf::detail::host_vector< OtherT > &in)
Definition: span.hpp:265
constexpr host_span(C const &in)
Definition: span.hpp:256
constexpr host_span(cudf::detail::host_vector< OtherT > const &in)
Definition: span.hpp:275
bool is_device_accessible() const
Returns whether the data is device accessible (e.g. pinned memory)
Definition: span.hpp:297
constexpr host_span(host_span< OtherT, OtherExtent > const &other) noexcept
Definition: span.hpp:287
constexpr host_span(C &in)
Definition: span.hpp:243
constexpr 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:306
constexpr host_span(T *data, std::size_t size, bool is_device_accessible)
Definition: span.hpp:229