span.hpp
前往此文件的文档。
1 /*
2  * 版权所有 (c) 2020-2025, NVIDIA CORPORATION。
3  *
4  * 根据 Apache 许可证 2.0 版(“许可证”)获得许可;
5  * 除非遵守许可证,否则您不得使用此文件。
6  * 您可以在以下位置获得许可证的副本
7  *
8  * https://apache.ac.cn/licenses/LICENSE-2.0
9  *
10  * 除非适用法律要求或书面同意,否则软件
11  * 根据许可证分发时按“原样”提供,
12  * 不附带任何明示或暗示的担保或条件。
13  * 请参阅许可证了解特定语言的管理权限和
14  * 限制。
15  */
16 
17 #pragma once
18 
19 #include <cudf/detail/utilities/host_vector.hpp>
20 #include <cudf/types.hpp>
21 #include <cudf/utilities/export.hpp>
22 
23 #include <rmm/device_buffer.hpp>
24 #include <rmm/device_uvector.hpp>
25 #include <rmm/device_vector.hpp>
26 
27 #include <thrust/detail/raw_pointer_cast.h>
28 #include <thrust/device_vector.h>
29 #include <thrust/host_vector.h>
30 #include <thrust/memory.h>
31 
32 #include <cstddef>
33 #include <limits>
34 #include <type_traits>
35 #include <utility>
36 
37 namespace CUDF_EXPORT cudf {
46 constexpr std::size_t dynamic_extent = std::numeric_limits<std::size_t>::max();
47  // 组结束
49 namespace detail {
50 
55 template <typename T, std::size_t Extent, typename Derived>
56 class span_base {
57  static_assert(Extent == dynamic_extent, "仅支持动态范围");
58 
59  public
60  using element_type = T;
61  using value_type = std::remove_cv<T>;
62  using size_type = std::size_t;
63  using difference_type = std::ptrdiff_t;
64  using pointer = T*;
65  using iterator = T*;
66  using const_pointer = T const*;
67  using reference = T&;
69  T const&;
70 
71  static constexpr std::size_t extent = Extent;
72 
73  CUDF_HOST_DEVICE constexpr span_base() noexcept {} // 复制构造函数。
80  CUDF_HOST_DEVICE constexpr span_base(pointer data, size_type size) : _data(data), _size(size) {}
81  // constexpr span_base(pointer begin, pointer end) : _data(begin), _size(end - begin) {}
82  CUDF_HOST_DEVICE constexpr span_base(span_base const&) noexcept = default;
88  CUDF_HOST_DEVICE constexpr span_base& operator=(span_base const&) noexcept = default;
89 
97  [[nodiscard]] CUDF_HOST_DEVICE constexpr iterator begin() const noexcept { return _data; }
105  [[nodiscard]] CUDF_HOST_DEVICE constexpr iterator end() const noexcept { return _data + _size; }
111  [[nodiscard]] CUDF_HOST_DEVICE constexpr pointer data() const noexcept { return _data; }
112 
118  [[nodiscard]] CUDF_HOST_DEVICE constexpr size_type size() const noexcept { return _size; }
124  [[nodiscard]] CUDF_HOST_DEVICE constexpr size_type size_bytes() const noexcept
125  {
126  return sizeof(T) * _size;
127  }
128 
134  [[nodiscard]] CUDF_HOST_DEVICE constexpr bool empty() const noexcept { return _size == 0; }
135 
142  [[nodiscard]] constexpr Derived first(size_type count) const noexcept
143  {
144  return Derived(_data, count);
145  }
146 
153  [[nodiscard]] constexpr Derived last(size_type count) const noexcept
154  {
155  return Derived(_data + _size - count, count);
156  }
157 
158  protected
159  pointer _data{nullptr};
160  size_type _size{0};
161 };
162 
163 } // namespace detail
164 
172 // ===== host_span =================================================================================
173 
174 template <typename T>
175 struct is_host_span_supported_container : std::false_type {};
176 
177 template <typename T, typename Alloc>
179  std::vector<T, Alloc>> : std::true_type {};
180 
181 template <typename T, typename Alloc>
183  thrust::host_vector<T, Alloc>> : std::true_type {};
184 
185 template <typename T, typename Alloc>
187  std::basic_string<T, std::char_traits<T>, Alloc>> : std::true_type {};
188 
193 template <typename T, std::size_t Extent = cudf::dynamic_extent>
194 struct host_span : public cudf::detail::span_base<T, Extent, host_span<T, Extent>> {
196  using base::base;
197 
198  constexpr host_span() noexcept : base() {} // centos 编译所需
199 
209  CUDF_HOST_DEVICE constexpr host_span(T* data, std::size_t size, bool is_device_accessible)
210  : base(data, size), _is_device_accessible{is_device_accessible}
211  {
212  }
213 
216  template <typename C,
217  // Only supported containers of types convertible to T
218  std::enable_if_t<is_host_span_supported_container<C>::value &&
219  std::is_convertible_v<
220  std::remove_pointer_t<decltype(thrust::raw_pointer_cast( // NOLINT
221  std::declval<C&>().data()))> (*)[],
222  T (*)[]>>* = nullptr> // NOLINT
223  constexpr host_span(C& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
224  {
225  }
226 
229  template <typename C,
230  // Only supported containers of types convertible to T
231  std::enable_if_t<is_host_span_supported_container<C>::value &&
232  std::is_convertible_v<
233  std::remove_pointer_t<decltype(thrust::raw_pointer_cast( // NOLINT
234  std::declval<C&>().data()))> (*)[],
235  T (*)[]>>* = nullptr> // NOLINT
236  constexpr host_span(C const& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
237  {
238  }
239 
242  template <typename OtherT,
243  // Only supported containers of types convertible to T
244  std::enable_if_t<std::is_convertible_v<OtherT (*)[], T (*)[]>>* = nullptr> // NOLINT
245  constexpr host_span(cudf::detail::host_vector<OtherT>& in)
246  : base(in.data(), in.size()), _is_device_accessible{in.get_allocator().is_device_accessible()}
247  {
248  }
249 
252  template <typename OtherT,
253  // Only supported containers of types convertible to T
254  std::enable_if_t<std::is_convertible_v<OtherT (*)[], T (*)[], void>>* = nullptr> // NOLINT
255  constexpr host_span(cudf::detail::host_vector<OtherT> const& in)
256  : base(in.data(), in.size()), _is_device_accessible{in.get_allocator().is_device_accessible()}
257  {
258  }
259 
260  // 拷贝构造以支持 const 转换
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 (*)[], // NOLINT
266  void>* = nullptr>
267  constexpr host_span(host_span<OtherT, OtherExtent> const& other) noexcept
268  : base(other.data(), other.size()), _is_device_accessible{other.is_device_accessible()}
269  {
270  }
271  // 如果 idx < 0 或 idx >= size,则行为未定义,因此不是 noexcept
281  constexpr typename base::reference operator[](typename base::size_type idx) const
282  {
283  static_assert(sizeof(idx) >= sizeof(size_t), "index type must not be smaller than size_t");
284  return this->_data[idx];
285  }
286 
287  // 如果 size = 0,则行为未定义,因此不是 noexcept
295  [[nodiscard]] constexpr typename base::reference front() const { return this->_data[0]; }
296  // 如果 size = 0,则行为未定义,因此不是 noexcept
304  [[nodiscard]] constexpr typename base::reference back() const
305  {
306  return this->_data[this->_size - 1];
307  }
308 
314  [[nodiscard]] bool is_device_accessible() const { return _is_device_accessible; }
315 
323  [[nodiscard]] CUDF_HOST_DEVICE constexpr host_span subspan(
324  typename base::size_type offset, typename base::size_type count) const noexcept
325  {
326  return host_span{this->data() + offset, count, _is_device_accessible};
327  }
328 
329  private
330  bool _is_device_accessible{false};
331 };
332 
333 // ===== device_span ===============================================================================
334 
335 template <typename T>
336 struct is_device_span_supported_container : std::false_type {};
337 
338 template <typename T, typename Alloc>
340  thrust::device_vector<T, Alloc>> : std::true_type {};
341 
342 template <typename T>
344  rmm::device_vector<T>> : std::true_type {};
345 
346 template <typename T>
348  rmm::device_uvector<T>> : std::true_type {};
349 
354 template <typename T, std::size_t Extent = cudf::dynamic_extent>
355 struct device_span : public cudf::detail::span_base<T, Extent, device_span<T, Extent>> {
357  using base::base;
358 
359  CUDF_HOST_DEVICE constexpr device_span() noexcept : base() {} // centos 编译所需
360 
363  template <typename C,
364  // Only supported containers of types convertible to T
365  std::enable_if_t<is_device_span_supported_container<C>::value &&
366  std::is_convertible_v<
367  std::remove_pointer_t<decltype(thrust::raw_pointer_cast( // NOLINT
368  std::declval<C&>().data()))> (*)[],
369  T (*)[]>>* = nullptr> // NOLINT
370  constexpr device_span(C& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
371  {
372  }
373 
376  template <typename C,
377  // Only supported containers of types convertible to T
378  std::enable_if_t<is_device_span_supported_container<C>::value &&
379  std::is_convertible_v<
380  std::remove_pointer_t<decltype(thrust::raw_pointer_cast( // NOLINT
381  std::declval<C&>().data()))> (*)[],
382  T (*)[]>>* = nullptr> // NOLINT
383  constexpr device_span(C const& in) : base(thrust::raw_pointer_cast(in.data()), in.size())
384  {
385  }
386 
387  // 拷贝构造以支持 const 转换
389  template <typename OtherT,
390  std::size_t OtherExtent,
391  std::enable_if_t<(Extent == OtherExtent || Extent == dynamic_extent) &&
392  std::is_convertible_v<OtherT (*)[], T (*)[], // NOLINT
393  void>* = nullptr>
395  : base(other.data(), other.size())
396  {
397  }
398 
399  // 如果 idx < 0 或 idx >= size,则行为未定义,因此不是 noexcept
409  __device__ constexpr typename base::reference operator[](typename base::size_type idx) const
410  {
411  static_assert(sizeof(idx) >= sizeof(size_t), "index type must not be smaller than size_t");
412  return this->_data[idx];
413  }
414 
415  // 如果 size = 0,则行为未定义,因此不是 noexcept
423  [[nodiscard]] __device__ constexpr typename base::reference front() const
424  {
425  return this->_data[0];
426  }
427  // 如果 size = 0,则行为未定义,因此不是 noexcept
435  [[nodiscard]] __device__ constexpr typename base::reference back() const
436  {
437  return this->_data[this->_size - 1];
438  }
439 
447  [[nodiscard]] CUDF_HOST_DEVICE constexpr device_span subspan(
448  typename base::size_type offset, typename base::size_type count) const noexcept
449  {
450  return device_span{this->data() + offset, count};
451  }
452 }; // 组结束
454 
455 namespace detail {
456 
462 template <typename T, template <typename, std::size_t> typename RowType>
463 class base_2dspan {
464  public
465  using size_type =
466  std::pair<size_t, size_t>
467 
468  constexpr base_2dspan() noexcept = default;
475  constexpr base_2dspan(RowType<T, dynamic_extent> flat_view, size_t columns)
476  : _flat{flat_view}, _size{columns == 0 ? 0 : flat_view.size() / columns, columns}
477  {
478 #ifndef __CUDA_ARCH__
479  CUDF_EXPECTS(_size.first * _size.second == flat_view.size(), "无效的二维跨度大小");
480 #endif
481  }
482 
488  [[nodiscard]] CUDF_HOST_DEVICE constexpr auto data() const noexcept { return _flat.data(); }
489 
495  [[nodiscard]] CUDF_HOST_DEVICE constexpr auto size() const noexcept { return _size; }
496 
502  [[nodiscard]] CUDF_HOST_DEVICE constexpr auto count() const noexcept { return _flat.size(); }
503 
509  [[nodiscard]] CUDF_HOST_DEVICE constexpr bool is_empty() const noexcept { return count() == 0; }
510 
520  CUDF_HOST_DEVICE constexpr RowType<T, dynamic_extent> operator[](std::size_t row) const
521  {
522  return _flat.subspan(row * _size.second, _size.second);
523  }
524 
530  [[nodiscard]] CUDF_HOST_DEVICE constexpr RowType<T, dynamic_extent> flat_view() const
531  {
532  return _flat;
533  }
534 
542  template <typename OtherT,
543  template <typename, size_t>
544  typename OtherRowType,
545  std::enable_if_t<std::is_convertible_v<OtherRowType<OtherT, dynamic_extent>,
546  RowType<T, dynamic_extent>>,
547  void>* = nullptr>
548  constexpr base_2dspan(base_2dspan<OtherT, OtherRowType> const& other) noexcept
549  : _flat{other.flat_view()}, _size{other.size()}
550  {
551  }
552 
553  protected
554  RowType<T, dynamic_extent> _flat;
555  size_type _size{0, 0};
556 };
557 
563 template <class T>
565 
571 template <class T>
573 
574 } // namespace detail
575 } // namespace CUDF_EXPORT cudf
行主序二维跨度的通用类。不兼容 STL 容器语义/语法。
定义: span.hpp:463
std::pair< size_t, size_t > size_type
用于表示跨度尺寸的类型。
定义: span.hpp:466
constexpr CUDF_HOST_DEVICE bool is_empty() const noexcept
检查跨度是否为空。
定义: span.hpp:509
constexpr CUDF_HOST_DEVICE auto size() const noexcept
返回跨度的尺寸作为一对值。
定义: span.hpp:495
constexpr CUDF_HOST_DEVICE auto count() const noexcept
返回跨度中的元素数量。
定义: span.hpp:502
constexpr CUDF_HOST_DEVICE RowType< T, dynamic_extent > operator[](std::size_t row) const
返回序列中第 `row` 行的引用。
定义: span.hpp:520
constexpr CUDF_HOST_DEVICE auto data() const noexcept
返回指向序列开头的指针。
定义: span.hpp:488
constexpr CUDF_HOST_DEVICE RowType< T, dynamic_extent > flat_view() const
返回该二维跨度的展平跨度。
定义: span.hpp:530
RowType< T, dynamic_extent > _flat
展平的二维跨度
定义: span.hpp:554
constexpr base_2dspan(base_2dspan< OtherT, OtherRowType > const &other) noexcept
从另一个可转换类型的二维跨度构造一个二维跨度。
定义: span.hpp:548
具有精简功能集的 C++20 std::span。
定义: span.hpp:56
std::size_t size_type
用于表示跨度大小的类型。
定义: span.hpp:62
constexpr CUDF_HOST_DEVICE iterator end() const noexcept
返回指向跨度中最后一个元素之后元素的迭代器。
定义: span.hpp:105
constexpr Derived first(size_type count) const noexcept
获取由序列前 N 个元素组成的子跨度。
定义: span.hpp:142
T * iterator
begin() 返回的迭代器类型
定义: span.hpp:65
constexpr CUDF_HOST_DEVICE pointer data() const noexcept
返回指向序列开头的指针。
定义: span.hpp:111
constexpr CUDF_HOST_DEVICE span_base & operator=(span_base const &) noexcept=default
复制构造函数。
constexpr CUDF_HOST_DEVICE size_type size() const noexcept
返回跨度中的元素数量。
定义: span.hpp:118
constexpr Derived last(size_type count) const noexcept
获取由序列后 N 个元素组成的子跨度。
定义: span.hpp:153
std::remove_cv< T > value_type
存储的值类型。
定义: span.hpp:61
std::ptrdiff_t difference_type
std::ptrdiff_t
定义: span.hpp:63
T * pointer
data() 返回的指针类型
定义: span.hpp:64
T const * const_pointer
data() const 返回的指针类型。
定义: span.hpp:66
constexpr CUDF_HOST_DEVICE span_base & operator=(span_base const &) noexcept=default
拷贝赋值运算符。
constexpr CUDF_HOST_DEVICE span_base(pointer data, size_type size)
从指针和大小构造一个跨度。
定义: span.hpp:80
T & reference
operator[](size_type) 返回的引用类型
定义: span.hpp:67
constexpr CUDF_HOST_DEVICE bool empty() const noexcept
检查跨度是否为空。
定义: span.hpp:134
constexpr CUDF_HOST_DEVICE iterator begin() const noexcept
返回指向跨度第一个元素的迭代器。
定义: span.hpp:97
constexpr CUDF_HOST_DEVICE size_type size_bytes() const noexcept
返回序列的大小(以字节为单位)。
定义: span.hpp:124
T const & const_reference
operator[](size_type) const 返回的引用类型。
定义: span.hpp:69
T element_type
跨度中的元素类型。
定义: span.hpp:60
thrust::device_vector< T, rmm::mr::thrust_allocator< T > > device_vector
#define CUDF_EXPECTS(...)
用于检查(前置)条件的宏,当条件不满足时抛出异常。
定义: error.hpp:178
constexpr std::size_t dynamic_extent
用于区分静态和动态范围的 std::span 的常量。
定义: span.hpp:46
cuDF 接口
定义: host_udf.hpp:37
具有精简功能集的 C++20 std::span 的设备版本。
定义: span.hpp:355
constexpr base::reference back() const
返回跨度中最后一个元素的引用。
定义: span.hpp:435
constexpr CUDF_HOST_DEVICE device_span(device_span< OtherT, OtherExtent > const &other) noexcept
定义: span.hpp:394
constexpr base::reference front() const
返回跨度中第一个元素的引用。
定义: span.hpp:423
constexpr CUDF_HOST_DEVICE device_span subspan(typename base::size_type offset, typename base::size_type count) const noexcept
获取一个子跨度,它是从此跨度中从 offset 开始的 count 个元素的视图。
定义: span.hpp:447
constexpr device_span(C &in)
定义: span.hpp:370
constexpr device_span(C const &in)
定义: span.hpp:383
constexpr base::reference operator[](typename base::size_type idx) const
返回序列中第 `idx` 个元素的引用。
定义: span.hpp:409
具有精简功能集的 C++20 std::span。
定义: span.hpp:194
constexpr base::reference front() const
返回跨度中第一个元素的引用。
定义: span.hpp:295
constexpr host_span(cudf::detail::host_vector< OtherT > &in)
定义: span.hpp:245
constexpr base::reference operator[](typename base::size_type idx) const
返回序列中第 `idx` 个元素的引用。
定义: span.hpp:281
constexpr host_span(C const &in)
定义: span.hpp:236
constexpr host_span(cudf::detail::host_vector< OtherT > const &in)
定义: span.hpp:255
bool is_device_accessible() const
返回数据是否可由设备访问(例如,固定内存)
定义: span.hpp:314
constexpr host_span(host_span< OtherT, OtherExtent > const &other) noexcept
定义: span.hpp:267
constexpr CUDF_HOST_DEVICE host_span(T *data, std::size_t size, bool is_device_accessible)
从指针和大小构造。
定义: span.hpp:209
constexpr base::reference back() const
返回跨度中最后一个元素的引用。
定义: span.hpp:304
constexpr host_span(C &in)
定义: span.hpp:223
constexpr CUDF_HOST_DEVICE host_span subspan(typename base::size_type offset, typename base::size_type count) const noexcept
获取一个子跨度,它是从此跨度中从 offset 开始的 count 个元素的视图。
定义: span.hpp:323
libcudf 的类型声明。
#define CUDF_HOST_DEVICE
表示该函数或方法可在主机和设备上使用。
定义: types.hpp:32