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 
190  [[nodiscard]] constexpr Derived subspan(size_type offset, size_type count) const noexcept
191  {
192  return Derived(_data + offset, count);
193  }
194 
195  private:
196  pointer _data{nullptr};
197  size_type _size{0};
198 };
199 
200 } // namespace detail
201 
209 // ===== host_span =================================================================================
210 
211 template <typename T>
212 struct is_host_span_supported_container : std::false_type {};
213 
214 template <typename T, typename Alloc>
216  std::vector<T, Alloc>> : std::true_type {};
217 
218 template <typename T, typename Alloc>
220  thrust::host_vector<T, Alloc>> : std::true_type {};
221 
222 template <typename T, typename Alloc>
224  std::basic_string<T, std::char_traits<T>, Alloc>> : std::true_type {};
225 
230 template <typename T, std::size_t Extent = cudf::dynamic_extent>
231 struct host_span : public cudf::detail::span_base<T, Extent, host_span<T, Extent>> {
233  using base::base;
234 
235  constexpr host_span() noexcept : base() {} // required to compile on centos
236 
239  template <
240  typename C,
241  // Only supported containers of types convertible to T
242  std::enable_if_t<is_host_span_supported_container<C>::value &&
243  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
244  std::declval<C&>().data()))> (*)[],
245  T (*)[]>>* = nullptr>
246  constexpr host_span(C& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
247  {
248  }
249 
252  template <
253  typename C,
254  // Only supported containers of types convertible to T
255  std::enable_if_t<is_host_span_supported_container<C>::value &&
256  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
257  std::declval<C&>().data()))> (*)[],
258  T (*)[]>>* = nullptr>
259  constexpr host_span(C const& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
260  {
261  }
262 
265  template <typename OtherT,
266  // Only supported containers of types convertible to T
267  std::enable_if_t<std::is_convertible_v<OtherT (*)[], T (*)[]>>* = nullptr>
268  constexpr host_span(cudf::detail::host_vector<OtherT>& in)
269  : base(in.data(), in.size()), _is_device_accessible{in.get_allocator().is_device_accessible()}
270  {
271  }
272 
275  template <typename OtherT,
276  // Only supported containers of types convertible to T
277  std::enable_if_t<std::is_convertible_v<OtherT (*)[], T (*)[]>>* = nullptr>
278  constexpr host_span(cudf::detail::host_vector<OtherT> const& in)
279  : base(in.data(), in.size()), _is_device_accessible{in.get_allocator().is_device_accessible()}
280  {
281  }
282 
283  // Copy construction to support const conversion
285  template <typename OtherT,
286  std::size_t OtherExtent,
287  std::enable_if_t<(Extent == OtherExtent || Extent == dynamic_extent) &&
288  std::is_convertible_v<OtherT (*)[], T (*)[]>,
289  void>* = nullptr>
290  constexpr host_span(host_span<OtherT, OtherExtent> const& other) noexcept
291  : base(other.data(), other.size())
292  {
293  }
294 
300  [[nodiscard]] bool is_device_accessible() const { return _is_device_accessible; }
301 
302  private:
303  bool _is_device_accessible{false};
304 };
305 
306 // ===== device_span ===============================================================================
307 
308 template <typename T>
309 struct is_device_span_supported_container : std::false_type {};
310 
311 template <typename T, typename Alloc>
313  thrust::device_vector<T, Alloc>> : std::true_type {};
314 
315 template <typename T>
317  rmm::device_vector<T>> : std::true_type {};
318 
319 template <typename T>
321  rmm::device_uvector<T>> : std::true_type {};
322 
327 template <typename T, std::size_t Extent = cudf::dynamic_extent>
328 struct device_span : public cudf::detail::span_base<T, Extent, device_span<T, Extent>> {
330  using base::base;
331 
332  constexpr device_span() noexcept : base() {} // required to compile on centos
333 
336  template <
337  typename C,
338  // Only supported containers of types convertible to T
339  std::enable_if_t<is_device_span_supported_container<C>::value &&
340  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
341  std::declval<C&>().data()))> (*)[],
342  T (*)[]>>* = nullptr>
343  constexpr device_span(C& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
344  {
345  }
346 
349  template <
350  typename C,
351  // Only supported containers of types convertible to T
352  std::enable_if_t<is_device_span_supported_container<C>::value &&
353  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
354  std::declval<C&>().data()))> (*)[],
355  T (*)[]>>* = nullptr>
356  constexpr device_span(C const& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
357  {
358  }
359 
360  // Copy construction to support const conversion
362  template <typename OtherT,
363  std::size_t OtherExtent,
364  std::enable_if_t<(Extent == OtherExtent || Extent == dynamic_extent) &&
365  std::is_convertible_v<OtherT (*)[], T (*)[]>,
366  void>* = nullptr>
367  constexpr device_span(device_span<OtherT, OtherExtent> const& other) noexcept
368  : base(other.data(), other.size())
369  {
370  }
371 }; // end of group
373 
374 namespace detail {
375 
381 template <typename T, template <typename, std::size_t> typename RowType>
382 class base_2dspan {
383  public:
384  using size_type =
385  std::pair<size_t, size_t>;
386 
387  constexpr base_2dspan() noexcept = default;
395  constexpr base_2dspan(T* data, size_t rows, size_t columns) noexcept
396  : _data{data}, _size{rows, columns}
397  {
398  }
405  base_2dspan(T* data, size_type size) noexcept : _data{data}, _size{std::move(size)} {}
406 
412  constexpr auto data() const noexcept { return _data; }
418  constexpr auto size() const noexcept { return _size; }
424  constexpr auto count() const noexcept { return size().first * size().second; }
430  [[nodiscard]] constexpr bool is_empty() const noexcept { return count() == 0; }
431 
440  static constexpr size_t flatten_index(size_t row, size_t column, size_type size) noexcept
441  {
442  return row * size.second + column;
443  }
444 
454  constexpr RowType<T, dynamic_extent> operator[](size_t row) const
455  {
456  return {this->data() + flatten_index(row, 0, this->size()), this->size().second};
457  }
458 
466  [[nodiscard]] constexpr RowType<T, dynamic_extent> front() const { return (*this)[0]; }
474  [[nodiscard]] constexpr RowType<T, dynamic_extent> back() const
475  {
476  return (*this)[size().first - 1];
477  }
478 
487  constexpr base_2dspan subspan(size_t first_row, size_t num_rows) const noexcept
488  {
489  return base_2dspan(
490  _data + flatten_index(first_row, 0, this->size()), num_rows, this->size().second);
491  }
492 
498  constexpr RowType<T, dynamic_extent> flat_view()
499  {
500  return {this->data(), this->size().first * this->size().second};
501  }
502 
510  template <typename OtherT,
511  template <typename, size_t>
512  typename OtherRowType,
513  std::enable_if_t<std::is_convertible_v<OtherRowType<OtherT, dynamic_extent>,
514  RowType<T, dynamic_extent>>,
515  void>* = nullptr>
516  constexpr base_2dspan(base_2dspan<OtherT, OtherRowType> const& other) noexcept
517  : _data{other.data()}, _size{other.size()}
518  {
519  }
520 
521  protected:
522  T* _data = nullptr;
523  size_type _size{0, 0};
524 };
525 
531 template <class T>
533 
539 template <class T>
541 
542 } // namespace detail
543 } // namespace CUDF_EXPORT cudf
A container of nullable device data as a column of elements.
Definition: column.hpp:47
Generic class for row-major 2D spans. Not compliant with STL container semantics/syntax.
Definition: span.hpp:382
std::pair< size_t, size_t > size_type
Type used to represent the dimension of the span.
Definition: span.hpp:385
constexpr auto count() const noexcept
Returns the number of elements in the span.
Definition: span.hpp:424
constexpr RowType< T, dynamic_extent > back() const
Returns a reference to the last element in the span.
Definition: span.hpp:474
constexpr bool is_empty() const noexcept
Checks if the span is empty.
Definition: span.hpp:430
constexpr auto data() const noexcept
Returns a pointer to the beginning of the sequence.
Definition: span.hpp:412
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:487
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:440
constexpr RowType< T, dynamic_extent > operator[](size_t row) const
Returns a reference to the row-th element of the sequence.
Definition: span.hpp:454
constexpr auto size() const noexcept
Returns the size in the span as pair.
Definition: span.hpp:418
constexpr RowType< T, dynamic_extent > front() const
Returns a reference to the first element in the span.
Definition: span.hpp:466
base_2dspan(T *data, size_type size) noexcept
Constructor a 2D span.
Definition: span.hpp:405
constexpr base_2dspan(base_2dspan< OtherT, OtherRowType > const &other) noexcept
Construct a 2D span from another 2D span of convertible type.
Definition: span.hpp:516
constexpr RowType< T, dynamic_extent > flat_view()
Returns a flattened span of the 2D span.
Definition: span.hpp:498
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
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:190
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
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:328
constexpr device_span(device_span< OtherT, OtherExtent > const &other) noexcept
Definition: span.hpp:367
constexpr device_span(C &in)
Definition: span.hpp:343
constexpr device_span(C const &in)
Definition: span.hpp:356
C++20 std::span with reduced feature set.
Definition: span.hpp:231
constexpr host_span(cudf::detail::host_vector< OtherT > &in)
Definition: span.hpp:268
constexpr host_span(C const &in)
Definition: span.hpp:259
constexpr host_span(cudf::detail::host_vector< OtherT > const &in)
Definition: span.hpp:278
bool is_device_accessible() const
Returns whether the data is device accessible (e.g. pinned memory)
Definition: span.hpp:300
constexpr host_span(host_span< OtherT, OtherExtent > const &other) noexcept
Definition: span.hpp:290
constexpr host_span(C &in)
Definition: span.hpp:246