device_uvector.hpp
转到此文件的文档。
1 /*
2  * Copyright (c) 2020-2025, 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  * https://apache.ac.cn/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/cuda_stream_view.hpp>
20 #include <rmm/detail/error.hpp>
21 #include <rmm/detail/exec_check_disable.hpp>
22 #include <rmm/detail/export.hpp>
23 #include <rmm/device_buffer.hpp>
25 #include <rmm/resource_ref.hpp>
26 
27 #include <cstddef>
28 #include <type_traits>
29 #include <utility>
30 
31 namespace RMM_NAMESPACE {
75 template <typename T>
77  static_assert(std::is_trivially_copyable_v<T>,
78  "device_uvector 仅支持可平凡复制的类型。");
79 
80  public
81  using value_type = T;
82  using size_type = std::size_t;
84  using const_reference = value_type const&
86  using pointer = value_type*;
87  using const_pointer = value_type const*;
88  using iterator = pointer;
90 
91  RMM_EXEC_CHECK_DISABLE
92  ~device_uvector() = default;
93 
94  RMM_EXEC_CHECK_DISABLE
95  device_uvector(device_uvector&&) noexcept = default;
96 
97  RMM_EXEC_CHECK_DISABLE
98  device_uvector& operator=(device_uvector&&) noexcept =
99  default;
100 
104  device_uvector(device_uvector const&) = delete;
105 
109  device_uvector& operator=(device_uvector const&) = delete;
110 
114  device_uvector() = delete;
115 
127  explicit device_uvector(std::size_t size,
128  cuda_stream_view stream,
130  : _storage{elements_to_bytes(size), stream, mr}
131  {
132  }
133 
143  explicit device_uvector(device_uvector const& other,
144  cuda_stream_view stream,
146  : _storage{other._storage, stream, mr}
147  {
148  }
149 
158  [[nodiscard]] pointer element_ptr(std::size_t element_index) noexcept
159  {
160  assert(element_index < size() && "尝试访问越界元素。");
161  return data() + element_index;
162  }
163 
172  [[nodiscard]] const_pointer element_ptr(std::size_t element_index) const noexcept
173  {
174  assert(element_index < size() && "尝试访问越界元素。");
175  return data() + element_index;
176  }
177 
214  void set_element_async(std::size_t element_index,
215  value_type const& value,
216  cuda_stream_view stream)
217  {
218  RMM_EXPECTS(
219  element_index < size(), "尝试访问越界元素。", rmm::out_of_range);
220 
221  if constexpr (std::is_same_v<value_type, bool>) {
222  RMM_CUDA_TRY(
223  cudaMemsetAsync(element_ptr(element_index), value, sizeof(value), stream.value()));
224  return;
225  }
226 
227  if constexpr (std::is_fundamental_v<value_type>) {
228  if (value == value_type{0}) {
229  set_element_to_zero_async(element_index, stream);
230  return;
231  }
232  }
233 
234  RMM_CUDA_TRY(cudaMemcpyAsync(
235  element_ptr(element_index), &value, sizeof(value), cudaMemcpyDefault, stream.value()));
236  }
237 
238  // 我们删除右值引用重载,以防止在字面值或隐式临时值被删除或超出范围后对其进行异步复制。
239  // We delete the r-value reference overload to prevent asynchronously copying from a literal or
240  // implicit temporary value after it is deleted or goes out of scope.
241  void set_element_async(std::size_t, value_type const&&, cuda_stream_view) = delete;
264  void set_element_to_zero_async(std::size_t element_index, cuda_stream_view stream)
265  {
266  RMM_EXPECTS(
267  element_index < size(), "尝试访问越界元素。", rmm::out_of_range);
268  RMM_CUDA_TRY(
269  cudaMemsetAsync(element_ptr(element_index), 0, sizeof(value_type), stream.value()));
270  }
271 
301  void set_element(std::size_t element_index, T const& value, cuda_stream_view stream)
302  {
303  set_element_async(element_index, value, stream);
304  stream.synchronize_no_throw();
305  }
306 
319  [[nodiscard]] value_type element(std::size_t element_index, cuda_stream_view stream) const
320  {
321  RMM_EXPECTS(
322  element_index < size(), "尝试访问越界元素。", rmm::out_of_range);
323  value_type value;
324  RMM_CUDA_TRY(cudaMemcpyAsync(
325  &value, element_ptr(element_index), sizeof(value), cudaMemcpyDefault, stream.value()));
326  stream.synchronize();
327  return value;
328  }
329 
341  [[nodiscard]] value_type front_element(cuda_stream_view stream) const
342  {
343  return element(0, stream);
344  }
345 
357  [[nodiscard]] value_type back_element(cuda_stream_view stream) const
358  {
359  return element(size() - 1, stream);
360  }
361 
374  void reserve(std::size_t new_capacity, cuda_stream_view stream)
375  {
376  _storage.reserve(elements_to_bytes(new_capacity), stream);
377  }
378 
395  void resize(std::size_t new_size, cuda_stream_view stream)
396  {
397  _storage.resize(elements_to_bytes(new_size), stream);
398  }
399 
407  void shrink_to_fit(cuda_stream_view stream) { _storage.shrink_to_fit(stream); }
408 
414  device_buffer release() noexcept { return std::move(_storage); }
415 
422  [[nodiscard]] std::size_t capacity() const noexcept
423  {
424  return bytes_to_elements(_storage.capacity());
425  }
426 
435  [[nodiscard]] pointer data() noexcept { return static_cast<pointer>(_storage.data()); }
436 
445  [[nodiscard]] const_pointer data() const noexcept
446  {
447  return static_cast<const_pointer>(_storage.data());
448  }
449 
457  [[nodiscard]] iterator begin() noexcept { return data(); }
458 
466  [[nodiscard]] const_iterator cbegin() const noexcept { return data(); }
467 
475  [[nodiscard]] const_iterator begin() const noexcept { return cbegin(); }
476 
485  [[nodiscard]] iterator end() noexcept { return data() + size(); }
486 
495  [[nodiscard]] const_iterator cend() const noexcept { return data() + size(); }
496 
505  [[nodiscard]] const_iterator end() const noexcept { return cend(); }
506 
510  [[nodiscard]] std::size_t size() const noexcept { return bytes_to_elements(_storage.size()); }
511 
515  [[nodiscard]] std::int64_t ssize() const noexcept
516  {
517  assert(size() < static_cast<std::size_t>(std::numeric_limits<int64_t>::max()) &&
518  "大小溢出有符号整数");
519  return static_cast<int64_t>(size());
520  }
521 
525  [[nodiscard]] bool is_empty() const noexcept { return size() == 0; }
526 
531  [[nodiscard]] rmm::device_async_resource_ref memory_resource() const noexcept
532  {
533  return _storage.memory_resource();
534  }
535 
539  [[nodiscard]] cuda_stream_view stream() const noexcept { return _storage.stream(); }
552  void set_stream(cuda_stream_view stream) noexcept { _storage.set_stream(stream); }
554  private
555  device_buffer _storage{};
556 
557  [[nodiscard]] std::size_t constexpr elements_to_bytes(std::size_t num_elements) const noexcept
558  {
559  return num_elements * sizeof(value_type);
560  }
561 
562  [[nodiscard]] std::size_t constexpr bytes_to_elements(std::size_t num_bytes) const noexcept
563  {
564  return num_bytes / sizeof(value_type);
565  }
566 };
567  // 组结束
569 } // namespace RMM_NAMESPACE
用于 CUDA stream 的强类型非拥有包装器,带默认构造函数。
定义: cuda_stream_view.hpp:39
constexpr cudaStream_t value() const noexcept
获取包装的 stream。
定义: cuda_stream_view.hpp:73
void synchronize() const
同步所查看的 CUDA stream。
定义: cuda_stream_view.hpp:106
void synchronize_no_throw() const noexcept
同步所查看的 CUDA stream。如果发生错误,不会抛出异常。
定义: cuda_stream_view.hpp:113
用于设备内存分配的 RAII 结构。
定义: device_buffer.hpp:82
设备内存中元素的未初始化向量。
定义: device_uvector.hpp:76
const_iterator cend() const noexcept
返回指向向量最后一个元素后一个元素的 const_iterator。
定义: device_uvector.hpp:495
std::size_t capacity() const noexcept
返回当前已分配存储中可容纳的元素数量。
定义: device_uvector.hpp:422
void resize(std::size_t new_size, cuda_stream_view stream)
将向量大小调整为包含 new_size 个元素。
定义: device_uvector.hpp:395
value_type * pointer
由 data() 返回的指针类型
定义: device_uvector.hpp:86
const_pointer element_ptr(std::size_t element_index) const noexcept
返回指向指定元素的指针。
定义: device_uvector.hpp:172
bool is_empty() const noexcept
如果向量不包含元素(即 size() == 0),则为 true
定义: device_uvector.hpp:525
const_pointer data() const noexcept
返回指向底层设备存储的 const 指针。
定义: device_uvector.hpp:445
std::size_t size() const noexcept
向量中的元素数量。
定义: device_uvector.hpp:510
pointer data() noexcept
返回指向底层设备存储的指针。
定义: device_uvector.hpp:435
void shrink_to_fit(cuda_stream_view stream)
强制解除分配未使用的设备内存。
定义: device_uvector.hpp:407
iterator end() noexcept
返回指向向量最后一个元素后一个元素的 iterator。
定义: device_uvector.hpp:485
std::size_t size_type
用于向量大小的类型。
定义: device_uvector.hpp:82
pointer element_ptr(std::size_t element_index) noexcept
返回指向指定元素的指针。
定义: device_uvector.hpp:158
std::int64_t ssize() const noexcept
向量中元素的带符号数量。
定义: device_uvector.hpp:515
T value_type
T;存储值的类型。
定义: device_uvector.hpp:81
const_iterator cbegin() const noexcept
返回指向第一个元素的 const_iterator。
定义: device_uvector.hpp:466
value_type back_element(cuda_stream_view stream) const
返回最后一个元素。
定义: device_uvector.hpp:357
void set_element_to_zero_async(std::size_t element_index, cuda_stream_view stream)
异步将设备内存中的指定元素设置为零。
定义: device_uvector.hpp:264
const_pointer const_iterator
由 cbegin() 返回的 const iterator 类型
定义: device_uvector.hpp:89
device_buffer release() noexcept
释放设备内存存储的所有权。
定义: device_uvector.hpp:414
void set_element_async(std::size_t element_index, value_type const &value, cuda_stream_view stream)
将 v 异步复制到设备内存中的指定元素。
定义: device_uvector.hpp:214
device_uvector(device_uvector &&) noexcept=default
默认移动构造函数。
pointer iterator
由 begin() 返回的 iterator 类型
定义: device_uvector.hpp:88
value_type & reference
value_type&;由 operator[](size_type) 返回的引用类型
定义: device_uvector.hpp:83
const_iterator end() const noexcept
返回指向向量最后一个元素后一个元素的 iterator。
定义: device_uvector.hpp:505
void reserve(std::size_t new_capacity, cuda_stream_view stream)
将向量的容量增加到 new_capacity 个元素。
定义: device_uvector.hpp:374
value_type element(std::size_t element_index, cuda_stream_view stream) const
从设备内存中返回指定的元素。
定义: device_uvector.hpp:319
value_type front_element(cuda_stream_view stream) const
返回第一个元素。
定义: device_uvector.hpp:341
value_type const * const_pointer
由 data() const 返回的指针类型。
定义: device_uvector.hpp:87
device_uvector(device_uvector const &other, cuda_stream_view stream, device_async_resource_ref mr=mr::get_current_device_resource_ref())
通过深度复制另一个 device_uvector 的内容来构造一个新的 device_uvector。
定义: device_uvector.hpp:143
value_type const & const_reference
定义: device_uvector.hpp:85
void set_element(std::size_t element_index, T const &value, cuda_stream_view stream)
将 v 同步复制到设备内存中的指定元素。
定义: device_uvector.hpp:301
const_iterator begin() const noexcept
返回指向第一个元素的 const_iterator。
定义: device_uvector.hpp:475
iterator begin() noexcept
返回指向第一个元素的 iterator。
定义: device_uvector.hpp:457
尝试访问定义范围之外时抛出的异常。
定义: error.hpp:110
cuda::mr::async_resource_ref< cuda::mr::device_accessible > device_async_resource_ref
具有 cuda::mr::device_accessible 属性的 cuda::mr::async_resource_ref 的别名。
定义: resource_ref.hpp:40
device_async_resource_ref get_current_device_resource_ref()
获取当前设备的 device_async_resource_ref。
定义: per_device_resource.hpp:411
管理每个设备的 device_memory_resources。