span.hpp
Go to the documentation of this file.
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 {
41 constexpr std::size_t dynamic_extent = std::numeric_limits<std::size_t>::max();
42  // end of group
44 namespace detail {
45 
50 template <typename T, std::size_t Extent, typename Derived>
51 class span_base {
52  static_assert(Extent == dynamic_extent, "Only dynamic extent is supported");
53 
54  public:
55  using element_type = T;
56  using value_type = std::remove_cv<T>;
57  using size_type = std::size_t;
58  using difference_type = std::ptrdiff_t;
59  using pointer = T*;
60  using iterator = T*;
61  using const_pointer = T const*;
62  using reference = T&;
64  T const&;
65 
66  static constexpr std::size_t extent = Extent;
67 
68  constexpr span_base() noexcept {}
75  constexpr span_base(pointer data, size_type size) : _data(data), _size(size) {}
76  // constexpr span_base(pointer begin, pointer end) : _data(begin), _size(end - begin) {}
77  constexpr span_base(span_base const&) noexcept = default;
83  constexpr span_base& operator=(span_base const&) noexcept = default;
84 
85  // not noexcept due to undefined behavior when size = 0
93  constexpr reference front() const { return _data[0]; }
94  // not noexcept due to undefined behavior when size = 0
102  constexpr reference back() const { return _data[_size - 1]; }
103  // not noexcept due to undefined behavior when idx < 0 || idx >= size
113  constexpr reference operator[](size_type idx) const { return _data[idx]; }
114 
122  constexpr iterator begin() const noexcept { return _data; }
130  constexpr iterator end() const noexcept { return _data + _size; }
136  constexpr pointer data() const noexcept { return _data; }
137 
143  [[nodiscard]] constexpr size_type size() const noexcept { return _size; }
149  [[nodiscard]] constexpr size_type size_bytes() const noexcept { return sizeof(T) * _size; }
155  [[nodiscard]] constexpr bool empty() const noexcept { return _size == 0; }
156 
163  constexpr Derived first(size_type count) const noexcept { return Derived(_data, count); }
164 
171  constexpr Derived last(size_type count) const noexcept
172  {
173  return Derived(_data + _size - count, count);
174  }
175 
183  constexpr Derived subspan(size_type offset, size_type count) const noexcept
184  {
185  return Derived(_data + offset, count);
186  }
187 
188  private:
189  pointer _data{nullptr};
190  size_type _size{0};
191 };
192 
193 } // namespace detail
194 
202 // ===== host_span =================================================================================
203 
204 template <typename T>
205 struct is_host_span_supported_container : std::false_type {};
206 
207 template <typename T, typename Alloc>
209  std::vector<T, Alloc>> : std::true_type {};
210 
211 template <typename T, typename Alloc>
213  thrust::host_vector<T, Alloc>> : std::true_type {};
214 
215 template <typename T, typename Alloc>
217  std::basic_string<T, std::char_traits<T>, Alloc>> : std::true_type {};
218 
223 template <typename T, std::size_t Extent = cudf::dynamic_extent>
224 struct host_span : public cudf::detail::span_base<T, Extent, host_span<T, Extent>> {
226  using base::base;
227 
228  constexpr host_span() noexcept : base() {} // required to compile on centos
229 
232  template <
233  typename C,
234  // Only supported containers of types convertible to T
235  std::enable_if_t<is_host_span_supported_container<C>::value &&
236  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
237  std::declval<C&>().data()))> (*)[],
238  T (*)[]>>* = nullptr>
239  constexpr host_span(C& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
240  {
241  }
242 
245  template <
246  typename C,
247  // Only supported containers of types convertible to T
248  std::enable_if_t<is_host_span_supported_container<C>::value &&
249  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
250  std::declval<C&>().data()))> (*)[],
251  T (*)[]>>* = nullptr>
252  constexpr host_span(C const& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
253  {
254  }
255 
256  // Copy construction to support const conversion
258  template <typename OtherT,
259  std::size_t OtherExtent,
260  std::enable_if_t<(Extent == OtherExtent || Extent == dynamic_extent) &&
261  std::is_convertible_v<OtherT (*)[], T (*)[]>,
262  void>* = nullptr>
263  constexpr host_span(host_span<OtherT, OtherExtent> const& other) noexcept
264  : base(other.data(), other.size())
265  {
266  }
267 };
268 
269 // ===== device_span ===============================================================================
270 
271 template <typename T>
272 struct is_device_span_supported_container : std::false_type {};
273 
274 template <typename T, typename Alloc>
276  thrust::device_vector<T, Alloc>> : std::true_type {};
277 
278 template <typename T>
280  rmm::device_vector<T>> : std::true_type {};
281 
282 template <typename T>
284  rmm::device_uvector<T>> : std::true_type {};
285 
290 template <typename T, std::size_t Extent = cudf::dynamic_extent>
291 struct device_span : public cudf::detail::span_base<T, Extent, device_span<T, Extent>> {
293  using base::base;
294 
295  constexpr device_span() noexcept : base() {} // required to compile on centos
296 
299  template <
300  typename C,
301  // Only supported containers of types convertible to T
302  std::enable_if_t<is_device_span_supported_container<C>::value &&
303  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
304  std::declval<C&>().data()))> (*)[],
305  T (*)[]>>* = nullptr>
306  constexpr device_span(C& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
307  {
308  }
309 
312  template <
313  typename C,
314  // Only supported containers of types convertible to T
315  std::enable_if_t<is_device_span_supported_container<C>::value &&
316  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
317  std::declval<C&>().data()))> (*)[],
318  T (*)[]>>* = nullptr>
319  constexpr device_span(C const& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
320  {
321  }
322 
323  // Copy construction to support const conversion
325  template <typename OtherT,
326  std::size_t OtherExtent,
327  std::enable_if_t<(Extent == OtherExtent || Extent == dynamic_extent) &&
328  std::is_convertible_v<OtherT (*)[], T (*)[]>,
329  void>* = nullptr>
330  constexpr device_span(device_span<OtherT, OtherExtent> const& other) noexcept
331  : base(other.data(), other.size())
332  {
333  }
334 }; // end of group
336 
337 namespace detail {
338 
344 template <typename T, template <typename, std::size_t> typename RowType>
345 class base_2dspan {
346  public:
347  using size_type =
348  std::pair<size_t, size_t>;
349 
350  constexpr base_2dspan() noexcept = default;
358  constexpr base_2dspan(T* data, size_t rows, size_t columns) noexcept
359  : _data{data}, _size{rows, columns}
360  {
361  }
369 
375  constexpr auto data() const noexcept { return _data; }
381  constexpr auto size() const noexcept { return _size; }
387  constexpr auto count() const noexcept { return size().first * size().second; }
393  [[nodiscard]] constexpr bool is_empty() const noexcept { return count() == 0; }
394 
403  static constexpr size_t flatten_index(size_t row, size_t column, size_type size) noexcept
404  {
405  return row * size.second + column;
406  }
407 
417  constexpr RowType<T, dynamic_extent> operator[](size_t row) const
418  {
419  return {this->data() + flatten_index(row, 0, this->size()), this->size().second};
420  }
421 
429  [[nodiscard]] constexpr RowType<T, dynamic_extent> front() const { return (*this)[0]; }
437  [[nodiscard]] constexpr RowType<T, dynamic_extent> back() const
438  {
439  return (*this)[size().first - 1];
440  }
441 
450  constexpr base_2dspan subspan(size_t first_row, size_t num_rows) const noexcept
451  {
452  return base_2dspan(
453  _data + flatten_index(first_row, 0, this->size()), num_rows, this->size().second);
454  }
455 
461  constexpr RowType<T, dynamic_extent> flat_view()
462  {
463  return {this->data(), this->size().first * this->size().second};
464  }
465 
473  template <typename OtherT,
474  template <typename, size_t>
475  typename OtherRowType,
476  std::enable_if_t<std::is_convertible_v<OtherRowType<OtherT, dynamic_extent>,
477  RowType<T, dynamic_extent>>,
478  void>* = nullptr>
479  constexpr base_2dspan(base_2dspan<OtherT, OtherRowType> const& other) noexcept
480  : _data{other.data()}, _size{other.size()}
481  {
482  }
483 
484  protected:
485  T* _data = nullptr;
486  size_type _size{0, 0};
487 };
488 
494 template <class T>
496 
502 template <class T>
504 
505 } // namespace detail
506 } // 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:345
std::pair< size_t, size_t > size_type
Type used to represent the dimension of the span.
Definition: span.hpp:348
constexpr auto count() const noexcept
Returns the number of elements in the span.
Definition: span.hpp:387
constexpr RowType< T, dynamic_extent > back() const
Returns a reference to the last element in the span.
Definition: span.hpp:437
constexpr bool is_empty() const noexcept
Checks if the span is empty.
Definition: span.hpp:393
size_type _size
rows, columns
Definition: span.hpp:486
constexpr auto data() const noexcept
Returns a pointer to the beginning of the sequence.
Definition: span.hpp:375
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:450
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:403
T * _data
pointer to the first element
Definition: span.hpp:485
constexpr RowType< T, dynamic_extent > operator[](size_t row) const
Returns a reference to the row-th element of the sequence.
Definition: span.hpp:417
constexpr auto size() const noexcept
Returns the size in the span as pair.
Definition: span.hpp:381
constexpr RowType< T, dynamic_extent > front() const
Returns a reference to the first element in the span.
Definition: span.hpp:429
base_2dspan(T *data, size_type size) noexcept
Constructor a 2D span.
Definition: span.hpp:368
constexpr base_2dspan(base_2dspan< OtherT, OtherRowType > const &other) noexcept
Construct a 2D span from another 2D span of convertible type.
Definition: span.hpp:479
constexpr RowType< T, dynamic_extent > flat_view()
Returns a flattened span of the 2D span.
Definition: span.hpp:461
C++20 std::span with reduced feature set.
Definition: span.hpp:51
constexpr iterator end() const noexcept
Returns an iterator to the element following the last element of the span.
Definition: span.hpp:130
std::size_t size_type
The type used for the size of the span.
Definition: span.hpp:57
constexpr bool empty() const noexcept
Checks if the span is empty.
Definition: span.hpp:155
constexpr reference operator[](size_type idx) const
Returns a reference to the idx-th element of the sequence.
Definition: span.hpp:113
constexpr reference back() const
Returns a reference to the last element in the span.
Definition: span.hpp:102
constexpr Derived first(size_type count) const noexcept
Obtains a subspan consisting of the first N elements of the sequence.
Definition: span.hpp:163
T * iterator
The type of the iterator returned by begin()
Definition: span.hpp:60
constexpr size_type size_bytes() const noexcept
Returns the size of the sequence in bytes.
Definition: span.hpp:149
constexpr span_base(pointer data, size_type size)
Constructs a span from a pointer and a size.
Definition: span.hpp:75
constexpr pointer data() const noexcept
Returns a pointer to the beginning of the sequence.
Definition: span.hpp:136
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:171
std::remove_cv< T > value_type
Stored value type.
Definition: span.hpp:56
std::ptrdiff_t difference_type
std::ptrdiff_t
Definition: span.hpp:58
T * pointer
The type of the pointer returned by data()
Definition: span.hpp:59
T const * const_pointer
The type of the pointer returned by data() const.
Definition: span.hpp:61
static constexpr std::size_t extent
The extent of the span.
Definition: span.hpp:66
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:183
T & reference
The type of the reference returned by operator[](size_type)
Definition: span.hpp:62
constexpr iterator begin() const noexcept
Returns an iterator to the first element of the span.
Definition: span.hpp:122
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:93
constexpr size_type size() const noexcept
Returns the number of elements in the span.
Definition: span.hpp:143
T const & const_reference
The type of the reference returned by operator[](size_type) const.
Definition: span.hpp:64
T element_type
The type of the elements in the span.
Definition: span.hpp:55
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:41
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:291
cudf::detail::span_base< T, Extent, device_span< T, Extent > > base
Base type.
Definition: span.hpp:292
constexpr device_span(device_span< OtherT, OtherExtent > const &other) noexcept
Definition: span.hpp:330
constexpr device_span(C &in)
Definition: span.hpp:306
constexpr device_span(C const &in)
Definition: span.hpp:319
C++20 std::span with reduced feature set.
Definition: span.hpp:224
constexpr host_span(C const &in)
Definition: span.hpp:252
constexpr host_span(host_span< OtherT, OtherExtent > const &other) noexcept
Definition: span.hpp:263
cudf::detail::span_base< T, Extent, host_span< T, Extent > > base
Base type.
Definition: span.hpp:225
constexpr host_span(C &in)
Definition: span.hpp:239