span.hpp
1 /*
2  * Copyright (c) 2020-2022, 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;
71 
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 
194 template <typename T, typename Alloc>
196  std::vector<T, Alloc>> : std::true_type {
197 };
198 
199 template <typename T, typename Alloc>
201  thrust::host_vector<T, Alloc>> : std::true_type {
202 };
203 
204 template <typename T, typename Alloc>
206  std::basic_string<T, std::char_traits<T>, Alloc>> : std::true_type {
207 };
208 
213 template <typename T, std::size_t Extent = cudf::dynamic_extent>
214 struct host_span : public cudf::detail::span_base<T, Extent, host_span<T, Extent>> {
216  using base::base;
217 
218  constexpr host_span() noexcept : base() {} // required to compile on centos
219 
222  template <
223  typename C,
224  // Only supported containers of types convertible to T
225  std::enable_if_t<is_host_span_supported_container<C>::value &&
226  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
227  std::declval<C&>().data()))> (*)[],
228  T (*)[]>>* = nullptr>
229  constexpr host_span(C& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
230  {
231  }
232 
235  template <
236  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<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
240  std::declval<C&>().data()))> (*)[],
241  T (*)[]>>* = nullptr>
242  constexpr host_span(C const& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
243  {
244  }
245 
246  // Copy construction to support const conversion
248  template <typename OtherT,
249  std::size_t OtherExtent,
250  std::enable_if_t<(Extent == OtherExtent || Extent == dynamic_extent) &&
251  std::is_convertible_v<OtherT (*)[], T (*)[]>,
252  void>* = nullptr>
253  constexpr host_span(const host_span<OtherT, OtherExtent>& other) noexcept
254  : base(other.data(), other.size())
255  {
256  }
257 };
258 
259 // ===== device_span ===============================================================================
260 
261 template <typename T>
262 struct is_device_span_supported_container : std::false_type {
263 };
264 
265 template <typename T, typename Alloc>
267  thrust::device_vector<T, Alloc>> : std::true_type {
268 };
269 
270 template <typename T>
272  rmm::device_vector<T>> : std::true_type {
273 };
274 
275 template <typename T>
277  rmm::device_uvector<T>> : std::true_type {
278 };
279 
284 template <typename T, std::size_t Extent = cudf::dynamic_extent>
285 struct device_span : public cudf::detail::span_base<T, Extent, device_span<T, Extent>> {
287  using base::base;
288 
289  constexpr device_span() noexcept : base() {} // required to compile on centos
290 
293  template <
294  typename C,
295  // Only supported containers of types convertible to T
296  std::enable_if_t<is_device_span_supported_container<C>::value &&
297  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
298  std::declval<C&>().data()))> (*)[],
299  T (*)[]>>* = nullptr>
300  constexpr device_span(C& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
301  {
302  }
303 
306  template <
307  typename C,
308  // Only supported containers of types convertible to T
309  std::enable_if_t<is_device_span_supported_container<C>::value &&
310  std::is_convertible_v<std::remove_pointer_t<decltype(thrust::raw_pointer_cast(
311  std::declval<C&>().data()))> (*)[],
312  T (*)[]>>* = nullptr>
313  constexpr device_span(C const& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
314  {
315  }
316 
317  // Copy construction to support const conversion
319  template <typename OtherT,
320  std::size_t OtherExtent,
321  std::enable_if_t<(Extent == OtherExtent || Extent == dynamic_extent) &&
322  std::is_convertible_v<OtherT (*)[], T (*)[]>,
323  void>* = nullptr>
324  constexpr device_span(const device_span<OtherT, OtherExtent>& other) noexcept
325  : base(other.data(), other.size())
326  {
327  }
328 };
329 
330 namespace detail {
331 
337 template <typename T, template <typename, std::size_t> typename RowType>
338 class base_2dspan {
339  public:
340  using size_type =
341  std::pair<size_t, size_t>;
342 
343  constexpr base_2dspan() noexcept = default;
351  constexpr base_2dspan(T* data, size_t rows, size_t columns) noexcept
352  : _data{data}, _size{rows, columns}
353  {
354  }
362 
368  constexpr auto data() const noexcept { return _data; }
374  constexpr auto size() const noexcept { return _size; }
380  constexpr auto count() const noexcept { return size().first * size().second; }
386  [[nodiscard]] constexpr bool is_empty() const noexcept { return count() == 0; }
387 
396  static constexpr size_t flatten_index(size_t row, size_t column, size_type size) noexcept
397  {
398  return row * size.second + column;
399  }
400 
410  constexpr RowType<T, dynamic_extent> operator[](size_t row) const
411  {
412  return {this->data() + flatten_index(row, 0, this->size()), this->size().second};
413  }
414 
422  [[nodiscard]] constexpr RowType<T, dynamic_extent> front() const { return (*this)[0]; }
430  [[nodiscard]] constexpr RowType<T, dynamic_extent> back() const
431  {
432  return (*this)[size().first - 1];
433  }
434 
443  constexpr base_2dspan subspan(size_t first_row, size_t num_rows) const noexcept
444  {
445  return base_2dspan(
446  _data + flatten_index(first_row, 0, this->size()), num_rows, this->size().second);
447  }
448 
454  constexpr RowType<T, dynamic_extent> flat_view()
455  {
456  return {this->data(), this->size().first * this->size().second};
457  }
458 
466  template <typename OtherT,
467  template <typename, size_t>
468  typename OtherRowType,
469  std::enable_if_t<std::is_convertible_v<OtherRowType<OtherT, dynamic_extent>,
470  RowType<T, dynamic_extent>>,
471  void>* = nullptr>
472  constexpr base_2dspan(base_2dspan<OtherT, OtherRowType> const& other) noexcept
473  : _data{other.data()}, _size{other.size()}
474  {
475  }
476 
477  protected:
478  T* _data = nullptr;
479  size_type _size{0, 0};
480 };
481 
487 template <class T>
488 using host_2dspan = base_2dspan<T, host_span>;
489 
495 template <class T>
496 using device_2dspan = base_2dspan<T, device_span>;
497 
498 } // namespace detail
499 } // namespace cudf
cudf::device_span::base
cudf::detail::span_base< T, Extent, device_span< T, Extent > > base
Base type.
Definition: span.hpp:286
cudf::detail::span_base::last
constexpr Derived last(size_type count) const noexcept
Obtains a subspan consisting of the last N elements of the sequence.
Definition: span.hpp:164
cudf::detail::span_base< detail::dremel_device_view const, cudf::dynamic_extent, device_span< detail::dremel_device_view const, cudf::dynamic_extent > >::value_type
std::remove_cv< detail::dremel_device_view const > value_type
Stored value type.
Definition: span.hpp:49
cudf::column
A container of nullable device data as a column of elements.
Definition: column.hpp:48
cudf::detail::base_2dspan::data
constexpr auto data() const noexcept
Returns a pointer to the beginning of the sequence.
Definition: span.hpp:368
cudf::detail::base_2dspan::_size
size_type _size
rows, columns
Definition: span.hpp:479
cudf::host_span::host_span
constexpr host_span(C const &in)
Definition: span.hpp:242
cudf::size_type
int32_t size_type
Row index type for columns and tables.
Definition: types.hpp:80
cudf::host_span::host_span
constexpr host_span(C &in)
Definition: span.hpp:229
cudf::detail::span_base::first
constexpr Derived first(size_type count) const noexcept
Obtains a subspan consisting of the first N elements of the sequence.
Definition: span.hpp:156
cudf::detail::base_2dspan
Generic class for row-major 2D spans. Not compliant with STL container semantics/syntax.
Definition: span.hpp:338
cudf::detail::span_base::subspan
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
cudf::host_span
C++20 std::span with reduced feature set.
Definition: span.hpp:214
rmm
cudf::detail::span_base::empty
constexpr bool empty() const noexcept
Checks if the span is empty.
Definition: span.hpp:148
cudf::detail::base_2dspan::operator[]
constexpr RowType< T, dynamic_extent > operator[](size_t row) const
Returns a reference to the row-th element of the sequence.
Definition: span.hpp:410
cudf::detail::span_base::back
constexpr reference back() const
Returns a reference to the last element in the span.
Definition: span.hpp:95
cudf::detail::span_base
C++20 std::span with reduced feature set.
Definition: span.hpp:44
cudf::detail::span_base::end
constexpr iterator end() const noexcept
Returns an iterator to the element following the last element of the span.
Definition: span.hpp:123
cudf::detail::span_base< detail::dremel_device_view const, cudf::dynamic_extent, device_span< detail::dremel_device_view const, cudf::dynamic_extent > >::element_type
detail::dremel_device_view const element_type
The type of the elements in the span.
Definition: span.hpp:48
cudf::host_span::host_span
constexpr host_span(const host_span< OtherT, OtherExtent > &other) noexcept
Definition: span.hpp:253
cudf::detail::span_base::size_bytes
constexpr size_type size_bytes() const noexcept
Returns the size of the sequence in bytes.
Definition: span.hpp:142
cudf::device_span::device_span
constexpr device_span(const device_span< OtherT, OtherExtent > &other) noexcept
Definition: span.hpp:324
cudf::host_span::base
cudf::detail::span_base< T, Extent, host_span< T, Extent > > base
Base type.
Definition: span.hpp:215
cudf::detail::base_2dspan::subspan
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:443
cudf::device_span::device_span
constexpr device_span(C const &in)
Definition: span.hpp:313
cudf::detail::base_2dspan::base_2dspan
base_2dspan(T *data, size_type size) noexcept
Constructor a 2D span.
Definition: span.hpp:361
device_buffer.hpp
cudf::detail::span_base::data
constexpr pointer data() const noexcept
Returns a pointer to the beginning of the sequence.
Definition: span.hpp:129
cudf::detail::span_base::operator[]
constexpr reference operator[](size_type idx) const
Returns a reference to the idx-th element of the sequence.
Definition: span.hpp:106
cudf::detail::span_base< detail::dremel_device_view const, cudf::dynamic_extent, device_span< detail::dremel_device_view const, cudf::dynamic_extent > >::const_pointer
detail::dremel_device_view const const * const_pointer
The type of the pointer returned by data() const.
Definition: span.hpp:54
cudf::is_host_span_supported_container
Definition: span.hpp:191
cudf::detail::span_base< detail::dremel_device_view const, cudf::dynamic_extent, device_span< detail::dremel_device_view const, cudf::dynamic_extent > >::size_type
std::size_t size_type
The type used for the size of the span.
Definition: span.hpp:50
cudf::detail::base_2dspan::_data
T * _data
pointer to the first element
Definition: span.hpp:478
cudf::detail::span_base::extent
static constexpr std::size_t extent
The extent of the span.
Definition: span.hpp:59
cudf::detail::base_2dspan::front
constexpr RowType< T, dynamic_extent > front() const
Returns a reference to the first element in the span.
Definition: span.hpp:422
cudf
cuDF interfaces
Definition: aggregation.hpp:34
cudf::detail::span_base< detail::dremel_device_view const, cudf::dynamic_extent, device_span< detail::dremel_device_view const, cudf::dynamic_extent > >::iterator
detail::dremel_device_view const * iterator
The type of the iterator returned by begin()
Definition: span.hpp:53
cudf::detail::base_2dspan::size_type
std::pair< size_t, size_t > size_type
Type used to represent the dimension of the span.
Definition: span.hpp:341
cudf::detail::base_2dspan::base_2dspan
constexpr base_2dspan(base_2dspan< OtherT, OtherRowType > const &other) noexcept
Construct a 2D span from another 2D span of convertible type.
Definition: span.hpp:472
cudf::detail::base_2dspan::is_empty
constexpr bool is_empty() const noexcept
Checks if the span is empty.
Definition: span.hpp:386
cudf::detail::span_base< detail::dremel_device_view const, cudf::dynamic_extent, device_span< detail::dremel_device_view const, cudf::dynamic_extent > >::const_reference
detail::dremel_device_view const const & const_reference
The type of the reference returned by operator[](size_type) const.
Definition: span.hpp:57
cudf::detail::span_base< detail::dremel_device_view const, cudf::dynamic_extent, device_span< detail::dremel_device_view const, cudf::dynamic_extent > >::difference_type
std::ptrdiff_t difference_type
std::ptrdiff_t
Definition: span.hpp:51
cudf::dynamic_extent
constexpr std::size_t dynamic_extent
A constant used to differentiate std::span of static and dynamic extent.
Definition: span.hpp:35
cudf::detail::span_base::span_base
constexpr span_base(span_base const &) noexcept=default
Copy constructor.
cudf::detail::base_2dspan::flat_view
constexpr RowType< T, dynamic_extent > flat_view()
Returns a flattened span of the 2D span.
Definition: span.hpp:454
cudf::detail::span_base::front
constexpr reference front() const
Returns a reference to the first element in the span.
Definition: span.hpp:86
cudf::detail::span_base< detail::dremel_device_view const, cudf::dynamic_extent, device_span< detail::dremel_device_view const, cudf::dynamic_extent > >::reference
detail::dremel_device_view const & reference
The type of the reference returned by operator[](size_type)
Definition: span.hpp:55
cudf::detail::base_2dspan::flatten_index
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:396
cudf::detail::base_2dspan::back
constexpr RowType< T, dynamic_extent > back() const
Returns a reference to the last element in the span.
Definition: span.hpp:430
cudf::detail::span_base< detail::dremel_device_view const, cudf::dynamic_extent, device_span< detail::dremel_device_view const, cudf::dynamic_extent > >::pointer
detail::dremel_device_view const * pointer
The type of the pointer returned by data()
Definition: span.hpp:52
cudf::device_span
Device version of C++20 std::span with reduced feature set.
Definition: span.hpp:285
cudf::detail::span_base::operator=
constexpr span_base & operator=(span_base const &) noexcept=default
Copy assignment operator.
cudf::detail::base_2dspan::size
constexpr auto size() const noexcept
Returns the size in the span as pair.
Definition: span.hpp:374
cudf::detail::span_base::span_base
constexpr span_base(pointer data, size_type size)
Constructs a span from a pointer and a size.
Definition: span.hpp:68
cudf::detail::base_2dspan::count
constexpr auto count() const noexcept
Returns the number of elements in the span.
Definition: span.hpp:380
cudf::detail::span_base::size
constexpr size_type size() const noexcept
Returns the number of elements in the span.
Definition: span.hpp:136
cudf::is_device_span_supported_container
Definition: span.hpp:262
cudf::device_span::device_span
constexpr device_span(C &in)
Definition: span.hpp:300
cudf::detail::span_base::begin
constexpr iterator begin() const noexcept
Returns an iterator to the first element of the span.
Definition: span.hpp:115