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 <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 #include <utility>
32 
33 namespace cudf {
42 constexpr std::size_t dynamic_extent = std::numeric_limits<std::size_t>::max();
43  // end of group
45 namespace detail {
46 
51 template <typename T, std::size_t Extent, typename Derived>
52 class span_base {
53  static_assert(Extent == dynamic_extent, "Only dynamic extent is supported");
54 
55  public:
56  using element_type = T;
57  using value_type = std::remove_cv<T>;
58  using size_type = std::size_t;
59  using difference_type = std::ptrdiff_t;
60  using pointer = T*;
61  using iterator = T*;
62  using const_pointer = T const*;
63  using reference = T&;
65  T const&;
66 
67  static constexpr std::size_t extent = Extent;
68 
69  constexpr span_base() noexcept {}
76  constexpr span_base(pointer data, size_type size) : _data(data), _size(size) {}
77  // constexpr span_base(pointer begin, pointer end) : _data(begin), _size(end - begin) {}
78  constexpr span_base(span_base const&) noexcept = default;
84  constexpr span_base& operator=(span_base const&) noexcept = default;
85 
86  // not noexcept due to undefined behavior when size = 0
94  [[nodiscard]] constexpr reference front() const { return _data[0]; }
95  // not noexcept due to undefined behavior when size = 0
103  [[nodiscard]] constexpr reference back() const { return _data[_size - 1]; }
104  // not noexcept due to undefined behavior when idx < 0 || idx >= size
114  constexpr reference operator[](size_type idx) const { return _data[idx]; }
115 
123  [[nodiscard]] constexpr iterator begin() const noexcept { return _data; }
131  [[nodiscard]] constexpr iterator end() const noexcept { return _data + _size; }
137  [[nodiscard]] constexpr pointer data() const noexcept { return _data; }
138 
144  [[nodiscard]] constexpr size_type size() const noexcept { return _size; }
150  [[nodiscard]] constexpr size_type size_bytes() const noexcept { return sizeof(T) * _size; }
156  [[nodiscard]] constexpr bool empty() const noexcept { return _size == 0; }
157 
164  [[nodiscard]] constexpr Derived first(size_type count) const noexcept
165  {
166  return Derived(_data, count);
167  }
168 
175  [[nodiscard]] constexpr Derived last(size_type count) const noexcept
176  {
177  return Derived(_data + _size - count, count);
178  }
179 
187  [[nodiscard]] constexpr Derived subspan(size_type offset, size_type count) const noexcept
188  {
189  return Derived(_data + offset, count);
190  }
191 
192  private:
193  pointer _data{nullptr};
194  size_type _size{0};
195 };
196 
197 } // namespace detail
198 
206 // ===== host_span =================================================================================
207 
208 template <typename T>
209 struct is_host_span_supported_container : std::false_type {};
210 
211 template <typename T, typename Alloc>
213  std::vector<T, Alloc>> : std::true_type {};
214 
215 template <typename T, typename Alloc>
217  thrust::host_vector<T, Alloc>> : std::true_type {};
218 
219 template <typename T, typename Alloc>
221  std::basic_string<T, std::char_traits<T>, Alloc>> : std::true_type {};
222 
227 template <typename T, std::size_t Extent = cudf::dynamic_extent>
228 struct host_span : public cudf::detail::span_base<T, Extent, host_span<T, Extent>> {
230  using base::base;
231 
232  constexpr host_span() noexcept : base() {} // required to compile on centos
233 
236  template <
237  typename C,
238  // Only supported containers of types convertible to T
239  std::enable_if_t<is_host_span_supported_container<C>::value &&
240  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
241  std::declval<C&>().data()))> (*)[],
242  T (*)[]>>* = nullptr>
243  constexpr host_span(C& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
244  {
245  }
246 
249  template <
250  typename C,
251  // Only supported containers of types convertible to T
252  std::enable_if_t<is_host_span_supported_container<C>::value &&
253  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
254  std::declval<C&>().data()))> (*)[],
255  T (*)[]>>* = nullptr>
256  constexpr host_span(C const& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
257  {
258  }
259 
260  // Copy construction to support const conversion
262  template <typename OtherT,
263  std::size_t OtherExtent,
264  std::enable_if_t<(Extent == OtherExtent || Extent == dynamic_extent) &&
265  std::is_convertible_v<OtherT (*)[], T (*)[]>,
266  void>* = nullptr>
267  constexpr host_span(host_span<OtherT, OtherExtent> const& other) noexcept
268  : base(other.data(), other.size())
269  {
270  }
271 };
272 
273 // ===== device_span ===============================================================================
274 
275 template <typename T>
276 struct is_device_span_supported_container : std::false_type {};
277 
278 template <typename T, typename Alloc>
280  thrust::device_vector<T, Alloc>> : std::true_type {};
281 
282 template <typename T>
284  rmm::device_vector<T>> : std::true_type {};
285 
286 template <typename T>
288  rmm::device_uvector<T>> : std::true_type {};
289 
294 template <typename T, std::size_t Extent = cudf::dynamic_extent>
295 struct device_span : public cudf::detail::span_base<T, Extent, device_span<T, Extent>> {
297  using base::base;
298 
299  constexpr device_span() noexcept : base() {} // required to compile on centos
300 
303  template <
304  typename C,
305  // Only supported containers of types convertible to T
306  std::enable_if_t<is_device_span_supported_container<C>::value &&
307  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
308  std::declval<C&>().data()))> (*)[],
309  T (*)[]>>* = nullptr>
310  constexpr device_span(C& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
311  {
312  }
313 
316  template <
317  typename C,
318  // Only supported containers of types convertible to T
319  std::enable_if_t<is_device_span_supported_container<C>::value &&
320  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
321  std::declval<C&>().data()))> (*)[],
322  T (*)[]>>* = nullptr>
323  constexpr device_span(C const& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
324  {
325  }
326 
327  // Copy construction to support const conversion
329  template <typename OtherT,
330  std::size_t OtherExtent,
331  std::enable_if_t<(Extent == OtherExtent || Extent == dynamic_extent) &&
332  std::is_convertible_v<OtherT (*)[], T (*)[]>,
333  void>* = nullptr>
334  constexpr device_span(device_span<OtherT, OtherExtent> const& other) noexcept
335  : base(other.data(), other.size())
336  {
337  }
338 }; // end of group
340 
341 namespace detail {
342 
348 template <typename T, template <typename, std::size_t> typename RowType>
349 class base_2dspan {
350  public:
351  using size_type =
352  std::pair<size_t, size_t>;
353 
354  constexpr base_2dspan() noexcept = default;
362  constexpr base_2dspan(T* data, size_t rows, size_t columns) noexcept
363  : _data{data}, _size{rows, columns}
364  {
365  }
372  base_2dspan(T* data, size_type size) noexcept : _data{data}, _size{std::move(size)} {}
373 
379  constexpr auto data() const noexcept { return _data; }
385  constexpr auto size() const noexcept { return _size; }
391  constexpr auto count() const noexcept { return size().first * size().second; }
397  [[nodiscard]] constexpr bool is_empty() const noexcept { return count() == 0; }
398 
407  static constexpr size_t flatten_index(size_t row, size_t column, size_type size) noexcept
408  {
409  return row * size.second + column;
410  }
411 
421  constexpr RowType<T, dynamic_extent> operator[](size_t row) const
422  {
423  return {this->data() + flatten_index(row, 0, this->size()), this->size().second};
424  }
425 
433  [[nodiscard]] constexpr RowType<T, dynamic_extent> front() const { return (*this)[0]; }
441  [[nodiscard]] constexpr RowType<T, dynamic_extent> back() const
442  {
443  return (*this)[size().first - 1];
444  }
445 
454  constexpr base_2dspan subspan(size_t first_row, size_t num_rows) const noexcept
455  {
456  return base_2dspan(
457  _data + flatten_index(first_row, 0, this->size()), num_rows, this->size().second);
458  }
459 
465  constexpr RowType<T, dynamic_extent> flat_view()
466  {
467  return {this->data(), this->size().first * this->size().second};
468  }
469 
477  template <typename OtherT,
478  template <typename, size_t>
479  typename OtherRowType,
480  std::enable_if_t<std::is_convertible_v<OtherRowType<OtherT, dynamic_extent>,
481  RowType<T, dynamic_extent>>,
482  void>* = nullptr>
483  constexpr base_2dspan(base_2dspan<OtherT, OtherRowType> const& other) noexcept
484  : _data{other.data()}, _size{other.size()}
485  {
486  }
487 
488  protected:
489  T* _data = nullptr;
490  size_type _size{0, 0};
491 };
492 
498 template <class T>
500 
506 template <class T>
508 
509 } // namespace detail
510 } // namespace cudf
A container of nullable device data as a column of elements.
Definition: column.hpp:48
Generic class for row-major 2D spans. Not compliant with STL container semantics/syntax.
Definition: span.hpp:349
std::pair< size_t, size_t > size_type
Type used to represent the dimension of the span.
Definition: span.hpp:352
constexpr auto count() const noexcept
Returns the number of elements in the span.
Definition: span.hpp:391
constexpr RowType< T, dynamic_extent > back() const
Returns a reference to the last element in the span.
Definition: span.hpp:441
constexpr bool is_empty() const noexcept
Checks if the span is empty.
Definition: span.hpp:397
size_type _size
rows, columns
Definition: span.hpp:490
constexpr auto data() const noexcept
Returns a pointer to the beginning of the sequence.
Definition: span.hpp:379
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:454
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:407
T * _data
pointer to the first element
Definition: span.hpp:489
constexpr RowType< T, dynamic_extent > operator[](size_t row) const
Returns a reference to the row-th element of the sequence.
Definition: span.hpp:421
constexpr auto size() const noexcept
Returns the size in the span as pair.
Definition: span.hpp:385
constexpr RowType< T, dynamic_extent > front() const
Returns a reference to the first element in the span.
Definition: span.hpp:433
base_2dspan(T *data, size_type size) noexcept
Constructor a 2D span.
Definition: span.hpp:372
constexpr base_2dspan(base_2dspan< OtherT, OtherRowType > const &other) noexcept
Construct a 2D span from another 2D span of convertible type.
Definition: span.hpp:483
constexpr RowType< T, dynamic_extent > flat_view()
Returns a flattened span of the 2D span.
Definition: span.hpp:465
C++20 std::span with reduced feature set.
Definition: span.hpp:52
constexpr iterator end() const noexcept
Returns an iterator to the element following the last element of the span.
Definition: span.hpp:131
std::size_t size_type
The type used for the size of the span.
Definition: span.hpp:58
constexpr bool empty() const noexcept
Checks if the span is empty.
Definition: span.hpp:156
constexpr reference operator[](size_type idx) const
Returns a reference to the idx-th element of the sequence.
Definition: span.hpp:114
constexpr reference back() const
Returns a reference to the last element in the span.
Definition: span.hpp:103
constexpr Derived first(size_type count) const noexcept
Obtains a subspan consisting of the first N elements of the sequence.
Definition: span.hpp:164
T * iterator
The type of the iterator returned by begin()
Definition: span.hpp:61
constexpr size_type size_bytes() const noexcept
Returns the size of the sequence in bytes.
Definition: span.hpp:150
constexpr span_base(pointer data, size_type size)
Constructs a span from a pointer and a size.
Definition: span.hpp:76
constexpr pointer data() const noexcept
Returns a pointer to the beginning of the sequence.
Definition: span.hpp:137
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:175
std::remove_cv< T > value_type
Stored value type.
Definition: span.hpp:57
std::ptrdiff_t difference_type
std::ptrdiff_t
Definition: span.hpp:59
T * pointer
The type of the pointer returned by data()
Definition: span.hpp:60
T const * const_pointer
The type of the pointer returned by data() const.
Definition: span.hpp:62
static constexpr std::size_t extent
The extent of the span.
Definition: span.hpp:67
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:187
T & reference
The type of the reference returned by operator[](size_type)
Definition: span.hpp:63
constexpr iterator begin() const noexcept
Returns an iterator to the first element of the span.
Definition: span.hpp:123
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:94
constexpr size_type size() const noexcept
Returns the number of elements in the span.
Definition: span.hpp:144
T const & const_reference
The type of the reference returned by operator[](size_type) const.
Definition: span.hpp:65
T element_type
The type of the elements in the span.
Definition: span.hpp:56
thrust::device_vector< T, rmm::mr::thrust_allocator< T > > device_vector
constexpr std::size_t dynamic_extent
A constant used to differentiate std::span of static and dynamic extent.
Definition: span.hpp:42
int32_t size_type
Row index type for columns and tables.
Definition: types.hpp:93
cuDF interfaces
Definition: aggregation.hpp:34
Device version of C++20 std::span with reduced feature set.
Definition: span.hpp:295
cudf::detail::span_base< T, Extent, device_span< T, Extent > > base
Base type.
Definition: span.hpp:296
constexpr device_span(device_span< OtherT, OtherExtent > const &other) noexcept
Definition: span.hpp:334
constexpr device_span(C &in)
Definition: span.hpp:310
constexpr device_span(C const &in)
Definition: span.hpp:323
C++20 std::span with reduced feature set.
Definition: span.hpp:228
constexpr host_span(C const &in)
Definition: span.hpp:256
constexpr host_span(host_span< OtherT, OtherExtent > const &other) noexcept
Definition: span.hpp:267
cudf::detail::span_base< T, Extent, host_span< T, Extent > > base
Base type.
Definition: span.hpp:229
constexpr host_span(C &in)
Definition: span.hpp:243