libcudf  23.12.00
span.hpp
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 {
33 
35 constexpr std::size_t dynamic_extent = std::numeric_limits<std::size_t>::max();
36 
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  constexpr span_base() noexcept {}
68  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  constexpr span_base(span_base const&) noexcept = default;
76  constexpr span_base& operator=(span_base const&) noexcept = default;
77 
78  // not noexcept due to undefined behavior when size = 0
86  constexpr reference front() const { return _data[0]; }
87  // not noexcept due to undefined behavior when size = 0
95  constexpr reference back() const { return _data[_size - 1]; }
96  // not noexcept due to undefined behavior when idx < 0 || idx >= size
106  constexpr reference operator[](size_type idx) const { return _data[idx]; }
107 
115  constexpr iterator begin() const noexcept { return _data; }
123  constexpr iterator end() const noexcept { return _data + _size; }
129  constexpr pointer data() const noexcept { return _data; }
130 
136  [[nodiscard]] constexpr size_type size() const noexcept { return _size; }
142  [[nodiscard]] constexpr size_type size_bytes() const noexcept { return sizeof(T) * _size; }
148  [[nodiscard]] constexpr bool empty() const noexcept { return _size == 0; }
149 
156  constexpr Derived first(size_type count) const noexcept { return Derived(_data, count); }
157 
164  constexpr Derived last(size_type count) const noexcept
165  {
166  return Derived(_data + _size - count, count);
167  }
168 
176  constexpr Derived subspan(size_type offset, size_type count) const noexcept
177  {
178  return Derived(_data + offset, count);
179  }
180 
181  private:
182  pointer _data{nullptr};
183  size_type _size{0};
184 };
185 
186 } // namespace detail
187 
188 // ===== host_span =================================================================================
189 
190 template <typename T>
191 struct is_host_span_supported_container : std::false_type {};
192 
193 template <typename T, typename Alloc>
195  std::vector<T, Alloc>> : std::true_type {};
196 
197 template <typename T, typename Alloc>
199  thrust::host_vector<T, Alloc>> : std::true_type {};
200 
201 template <typename T, typename Alloc>
203  std::basic_string<T, std::char_traits<T>, Alloc>> : std::true_type {};
204 
209 template <typename T, std::size_t Extent = cudf::dynamic_extent>
210 struct host_span : public cudf::detail::span_base<T, Extent, host_span<T, Extent>> {
212  using base::base;
213 
214  constexpr host_span() noexcept : base() {} // required to compile on centos
215 
218  template <
219  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<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
223  std::declval<C&>().data()))> (*)[],
224  T (*)[]>>* = nullptr>
225  constexpr host_span(C& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
226  {
227  }
228 
231  template <
232  typename C,
233  // Only supported containers of types convertible to T
234  std::enable_if_t<is_host_span_supported_container<C>::value &&
235  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
236  std::declval<C&>().data()))> (*)[],
237  T (*)[]>>* = nullptr>
238  constexpr host_span(C const& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
239  {
240  }
241 
242  // Copy construction to support const conversion
244  template <typename OtherT,
245  std::size_t OtherExtent,
246  std::enable_if_t<(Extent == OtherExtent || Extent == dynamic_extent) &&
247  std::is_convertible_v<OtherT (*)[], T (*)[]>,
248  void>* = nullptr>
249  constexpr host_span(host_span<OtherT, OtherExtent> const& other) noexcept
250  : base(other.data(), other.size())
251  {
252  }
253 };
254 
255 // ===== device_span ===============================================================================
256 
257 template <typename T>
258 struct is_device_span_supported_container : std::false_type {};
259 
260 template <typename T, typename Alloc>
262  thrust::device_vector<T, Alloc>> : std::true_type {};
263 
264 template <typename T>
266  rmm::device_vector<T>> : std::true_type {};
267 
268 template <typename T>
270  rmm::device_uvector<T>> : std::true_type {};
271 
276 template <typename T, std::size_t Extent = cudf::dynamic_extent>
277 struct device_span : public cudf::detail::span_base<T, Extent, device_span<T, Extent>> {
279  using base::base;
280 
281  constexpr device_span() noexcept : base() {} // required to compile on centos
282 
285  template <
286  typename C,
287  // Only supported containers of types convertible to T
288  std::enable_if_t<is_device_span_supported_container<C>::value &&
289  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
290  std::declval<C&>().data()))> (*)[],
291  T (*)[]>>* = nullptr>
292  constexpr device_span(C& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
293  {
294  }
295 
298  template <
299  typename C,
300  // Only supported containers of types convertible to T
301  std::enable_if_t<is_device_span_supported_container<C>::value &&
302  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
303  std::declval<C&>().data()))> (*)[],
304  T (*)[]>>* = nullptr>
305  constexpr device_span(C const& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
306  {
307  }
308 
309  // Copy construction to support const conversion
311  template <typename OtherT,
312  std::size_t OtherExtent,
313  std::enable_if_t<(Extent == OtherExtent || Extent == dynamic_extent) &&
314  std::is_convertible_v<OtherT (*)[], T (*)[]>,
315  void>* = nullptr>
316  constexpr device_span(device_span<OtherT, OtherExtent> const& other) noexcept
317  : base(other.data(), other.size())
318  {
319  }
320 };
321 
322 namespace detail {
323 
329 template <typename T, template <typename, std::size_t> typename RowType>
330 class base_2dspan {
331  public:
332  using size_type =
333  std::pair<size_t, size_t>;
334 
335  constexpr base_2dspan() noexcept = default;
343  constexpr base_2dspan(T* data, size_t rows, size_t columns) noexcept
344  : _data{data}, _size{rows, columns}
345  {
346  }
354 
360  constexpr auto data() const noexcept { return _data; }
366  constexpr auto size() const noexcept { return _size; }
372  constexpr auto count() const noexcept { return size().first * size().second; }
378  [[nodiscard]] constexpr bool is_empty() const noexcept { return count() == 0; }
379 
388  static constexpr size_t flatten_index(size_t row, size_t column, size_type size) noexcept
389  {
390  return row * size.second + column;
391  }
392 
402  constexpr RowType<T, dynamic_extent> operator[](size_t row) const
403  {
404  return {this->data() + flatten_index(row, 0, this->size()), this->size().second};
405  }
406 
414  [[nodiscard]] constexpr RowType<T, dynamic_extent> front() const { return (*this)[0]; }
422  [[nodiscard]] constexpr RowType<T, dynamic_extent> back() const
423  {
424  return (*this)[size().first - 1];
425  }
426 
435  constexpr base_2dspan subspan(size_t first_row, size_t num_rows) const noexcept
436  {
437  return base_2dspan(
438  _data + flatten_index(first_row, 0, this->size()), num_rows, this->size().second);
439  }
440 
446  constexpr RowType<T, dynamic_extent> flat_view()
447  {
448  return {this->data(), this->size().first * this->size().second};
449  }
450 
458  template <typename OtherT,
459  template <typename, size_t>
460  typename OtherRowType,
461  std::enable_if_t<std::is_convertible_v<OtherRowType<OtherT, dynamic_extent>,
462  RowType<T, dynamic_extent>>,
463  void>* = nullptr>
464  constexpr base_2dspan(base_2dspan<OtherT, OtherRowType> const& other) noexcept
465  : _data{other.data()}, _size{other.size()}
466  {
467  }
468 
469  protected:
470  T* _data = nullptr;
471  size_type _size{0, 0};
472 };
473 
479 template <class T>
480 using host_2dspan = base_2dspan<T, host_span>;
481 
487 template <class T>
488 using device_2dspan = base_2dspan<T, device_span>;
489 
490 } // namespace detail
491 } // 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:330
std::pair< size_t, size_t > size_type
Type used to represent the dimension of the span.
Definition: span.hpp:333
constexpr auto count() const noexcept
Returns the number of elements in the span.
Definition: span.hpp:372
constexpr RowType< T, dynamic_extent > back() const
Returns a reference to the last element in the span.
Definition: span.hpp:422
constexpr bool is_empty() const noexcept
Checks if the span is empty.
Definition: span.hpp:378
size_type _size
rows, columns
Definition: span.hpp:471
constexpr auto data() const noexcept
Returns a pointer to the beginning of the sequence.
Definition: span.hpp:360
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:435
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:388
T * _data
pointer to the first element
Definition: span.hpp:470
constexpr RowType< T, dynamic_extent > operator[](size_t row) const
Returns a reference to the row-th element of the sequence.
Definition: span.hpp:402
constexpr auto size() const noexcept
Returns the size in the span as pair.
Definition: span.hpp:366
constexpr RowType< T, dynamic_extent > front() const
Returns a reference to the first element in the span.
Definition: span.hpp:414
base_2dspan(T *data, size_type size) noexcept
Constructor a 2D span.
Definition: span.hpp:353
constexpr base_2dspan(base_2dspan< OtherT, OtherRowType > const &other) noexcept
Construct a 2D span from another 2D span of convertible type.
Definition: span.hpp:464
constexpr RowType< T, dynamic_extent > flat_view()
Returns a flattened span of the 2D span.
Definition: span.hpp:446
C++20 std::span with reduced feature set.
Definition: span.hpp:44
constexpr iterator end() const noexcept
Returns an iterator to the element following the last element of the span.
Definition: span.hpp:123
std::size_t size_type
The type used for the size of the span.
Definition: span.hpp:50
constexpr bool empty() const noexcept
Checks if the span is empty.
Definition: span.hpp:148
constexpr reference operator[](size_type idx) const
Returns a reference to the idx-th element of the sequence.
Definition: span.hpp:106
constexpr reference back() const
Returns a reference to the last element in 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:156
T * iterator
The type of the iterator returned by begin()
Definition: span.hpp:53
constexpr size_type size_bytes() const noexcept
Returns the size of the sequence in bytes.
Definition: span.hpp:142
constexpr span_base(pointer data, size_type size)
Constructs a span from a pointer and a size.
Definition: span.hpp:68
constexpr pointer data() const noexcept
Returns a pointer to the beginning of the sequence.
Definition: span.hpp:129
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:164
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
static constexpr std::size_t extent
The extent of the span.
Definition: span.hpp:59
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:176
T & reference
The type of the reference returned by operator[](size_type)
Definition: span.hpp:55
constexpr iterator begin() const noexcept
Returns an iterator to the first element of the span.
Definition: span.hpp:115
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:86
constexpr size_type size() const noexcept
Returns the number of elements in the span.
Definition: span.hpp:136
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
int32_t size_type
Row index type for columns and tables.
Definition: types.hpp:80
cuDF interfaces
Definition: aggregation.hpp:34
constexpr std::size_t dynamic_extent
A constant used to differentiate std::span of static and dynamic extent.
Definition: span.hpp:35
Device version of C++20 std::span with reduced feature set.
Definition: span.hpp:277
cudf::detail::span_base< T, Extent, device_span< T, Extent > > base
Base type.
Definition: span.hpp:278
constexpr device_span(device_span< OtherT, OtherExtent > const &other) noexcept
Definition: span.hpp:316
constexpr device_span(C &in)
Definition: span.hpp:292
constexpr device_span(C const &in)
Definition: span.hpp:305
C++20 std::span with reduced feature set.
Definition: span.hpp:210
constexpr host_span(C const &in)
Definition: span.hpp:238
constexpr host_span(host_span< OtherT, OtherExtent > const &other) noexcept
Definition: span.hpp:249
cudf::detail::span_base< T, Extent, host_span< T, Extent > > base
Base type.
Definition: span.hpp:211
constexpr host_span(C &in)
Definition: span.hpp:225