device_uvector.hpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #pragma once
7 
9 #include <rmm/detail/cuda_memcpy.hpp>
10 #include <rmm/detail/error.hpp>
11 #include <rmm/detail/exec_check_disable.hpp>
12 #include <rmm/detail/export.hpp>
13 #include <rmm/device_buffer.hpp>
15 #include <rmm/resource_ref.hpp>
16 
17 #include <cuda/std/iterator>
18 #include <cuda/std/span>
19 
20 #include <cstddef>
21 #include <limits>
22 #include <type_traits>
23 #include <utility>
24 
25 RMM_NAMESPACE_BEGIN
69 template <typename T>
71  static_assert(std::is_trivially_copyable_v<T>,
72  "device_uvector only supports types that are trivially copyable.");
73 
74  public:
75  using value_type = T;
76  using size_type = std::size_t;
77  using reference = value_type&;
79  value_type const&;
80  using pointer = value_type*;
81  using const_pointer = value_type const*;
82  using iterator = pointer;
85  cuda::std::reverse_iterator<iterator>;
87  cuda::std::reverse_iterator<const_iterator>;
89 
90  RMM_EXEC_CHECK_DISABLE
91  ~device_uvector() = default;
92 
93  RMM_EXEC_CHECK_DISABLE
94  device_uvector(device_uvector&&) noexcept = default;
95 
96  RMM_EXEC_CHECK_DISABLE
97  device_uvector& operator=(device_uvector&&) noexcept =
98  default;
99 
103  device_uvector(device_uvector const&) = delete;
104 
108  device_uvector& operator=(device_uvector const&) = delete;
109 
113  device_uvector() = delete;
114 
130  explicit device_uvector(
131  size_type size,
132  cuda_stream_view stream,
133  cuda::mr::any_resource<cuda::mr::device_accessible> mr = mr::get_current_device_resource_ref())
134  : _storage{elements_to_bytes(size), std::alignment_of_v<T>, stream, std::move(mr)}
135  {
136  }
137 
147  explicit device_uvector(
148  device_uvector const& other,
149  cuda_stream_view stream,
150  cuda::mr::any_resource<cuda::mr::device_accessible> mr = mr::get_current_device_resource_ref())
151  : _storage{other._storage, stream, std::move(mr)}
152  {
153  }
154 
163  [[nodiscard]] pointer element_ptr(size_type element_index) noexcept
164  {
165  assert(element_index < size());
166  return data() + element_index;
167  }
168 
177  [[nodiscard]] const_pointer element_ptr(size_type element_index) const noexcept
178  {
179  assert(element_index < size());
180  return data() + element_index;
181  }
182 
216  void set_element_async(size_type element_index, value_type const& value, cuda_stream_view stream)
217  {
218  RMM_EXPECTS(
219  element_index < size(), "Attempt to access out of bounds element.", rmm::out_of_range);
220  RMM_CUDA_TRY(
221  rmm::detail::memcpy_async(element_ptr(element_index), &value, sizeof(value), stream));
222  }
223 
224  // We delete the r-value reference overload to prevent asynchronously copying from a literal or
225  // implicit temporary value after it is deleted or goes out of scope.
226  void set_element_async(size_type, value_type const&&, cuda_stream_view) = delete;
227 
251  {
252  RMM_EXPECTS(
253  element_index < size(), "Attempt to access out of bounds element.", rmm::out_of_range);
254  RMM_CUDA_TRY(
255  cudaMemsetAsync(element_ptr(element_index), 0, sizeof(value_type), stream.value()));
256  }
257 
287  void set_element(size_type element_index, T const& value, cuda_stream_view stream)
288  {
289  set_element_async(element_index, value, stream);
290  stream.synchronize_no_throw();
291  }
292 
305  [[nodiscard]] value_type element(size_type element_index, cuda_stream_view stream) const
306  {
307  RMM_EXPECTS(
308  element_index < size(), "Attempt to access out of bounds element.", rmm::out_of_range);
309  value_type value;
310  RMM_CUDA_TRY(
311  rmm::detail::memcpy_async(&value, element_ptr(element_index), sizeof(value), stream));
312  stream.synchronize();
313  return value;
314  }
315 
327  [[nodiscard]] value_type front_element(cuda_stream_view stream) const
328  {
329  return element(0, stream);
330  }
331 
343  [[nodiscard]] value_type back_element(cuda_stream_view stream) const
344  {
345  return element(size() - 1, stream);
346  }
347 
362  void reserve(size_type new_capacity, cuda_stream_view stream)
363  {
364  _storage.reserve(elements_to_bytes(new_capacity), stream);
365  }
366 
385  void resize(size_type new_size, cuda_stream_view stream)
386  {
387  _storage.resize(elements_to_bytes(new_size), stream);
388  }
389 
397  void shrink_to_fit(cuda_stream_view stream) { _storage.shrink_to_fit(stream); }
398 
404  device_buffer release() noexcept { return std::move(_storage); }
405 
412  [[nodiscard]] size_type capacity() const noexcept
413  {
414  return bytes_to_elements(_storage.capacity());
415  }
416 
425  [[nodiscard]] pointer data() noexcept { return static_cast<pointer>(_storage.data()); }
426 
435  [[nodiscard]] const_pointer data() const noexcept
436  {
437  return static_cast<const_pointer>(_storage.data());
438  }
439 
447  [[nodiscard]] iterator begin() noexcept { return data(); }
448 
456  [[nodiscard]] const_iterator cbegin() const noexcept { return data(); }
457 
465  [[nodiscard]] const_iterator begin() const noexcept { return cbegin(); }
466 
475  [[nodiscard]] iterator end() noexcept { return data() + size(); }
476 
485  [[nodiscard]] const_iterator cend() const noexcept { return data() + size(); }
486 
495  [[nodiscard]] const_iterator end() const noexcept { return cend(); }
496 
504  [[nodiscard]] reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
505 
513  [[nodiscard]] const_reverse_iterator crbegin() const noexcept
514  {
515  return const_reverse_iterator(cend());
516  }
517 
525  [[nodiscard]] const_reverse_iterator rbegin() const noexcept { return crbegin(); }
526 
535  [[nodiscard]] reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
536 
546  [[nodiscard]] const_reverse_iterator crend() const noexcept
547  {
548  return const_reverse_iterator(begin());
549  }
550 
559  [[nodiscard]] const_reverse_iterator rend() const noexcept { return crend(); }
560 
564  [[nodiscard]] size_type size() const noexcept { return bytes_to_elements(_storage.size()); }
565 
569  [[nodiscard]] std::int64_t ssize() const noexcept
570  {
571  assert(size() < static_cast<size_type>(std::numeric_limits<int64_t>::max()) &&
572  "Size overflows signed integer");
573  return static_cast<int64_t>(size());
574  }
575 
579  [[nodiscard]] bool is_empty() const noexcept { return size() == 0; }
580 
584  [[nodiscard]] operator cuda::std::span<T const>() const noexcept
585  {
586  return cuda::std::span<T const>(data(), size());
587  }
588 
592  [[nodiscard]] operator cuda::std::span<T>() noexcept
593  {
594  return cuda::std::span<T>(data(), size());
595  }
596 
601  [[nodiscard]] rmm::device_async_resource_ref memory_resource() noexcept
602  {
603  return _storage.memory_resource();
604  }
605 
609  [[nodiscard]] cuda_stream_view stream() const noexcept { return _storage.stream(); }
610 
622  void set_stream(cuda_stream_view stream) noexcept { _storage.set_stream(stream); }
623 
624  private:
625  device_buffer _storage{};
626 
627  [[nodiscard]] size_type elements_to_bytes(size_type num_elements) const
628  {
629  RMM_EXPECTS(num_elements <= std::numeric_limits<size_type>::max() / sizeof(value_type),
630  "Requested size overflows device_uvector storage.",
632  return num_elements * sizeof(value_type);
633  }
634 
635  [[nodiscard]] size_type constexpr bytes_to_elements(size_type num_bytes) const noexcept
636  {
637  return num_bytes / sizeof(value_type);
638  }
639 };
640  // end of group
642 RMM_NAMESPACE_END
Strongly-typed non-owning wrapper for CUDA streams with default constructor.
Definition: cuda_stream_view.hpp:28
void synchronize() const
Synchronize the viewed CUDA stream.
void synchronize_no_throw() const noexcept
Synchronize the viewed CUDA stream. Does not throw if there is an error.
cudaStream_t value() const noexcept
Get the wrapped stream.
RAII construct for device memory allocation.
Definition: device_buffer.hpp:72
An uninitialized vector of elements in device memory.
Definition: device_uvector.hpp:70
reverse_iterator rend() noexcept
Returns reverse_iterator to the element preceding the first element of the vector.
Definition: device_uvector.hpp:535
const_iterator cend() const noexcept
Returns a const_iterator to the element following the last element of the vector.
Definition: device_uvector.hpp:485
const_reverse_iterator crend() const noexcept
Returns a const_reverse_iterator to the element preceding the first element of the vector.
Definition: device_uvector.hpp:546
value_type * pointer
The type of the pointer returned by data()
Definition: device_uvector.hpp:80
cuda::std::reverse_iterator< iterator > reverse_iterator
The type of the iterator returned by rbegin()
Definition: device_uvector.hpp:85
void set_element_async(size_type element_index, value_type const &value, cuda_stream_view stream)
Performs an asynchronous copy of v to the specified element in device memory.
Definition: device_uvector.hpp:216
bool is_empty() const noexcept
true if the vector contains no elements, i.e. size() == 0
Definition: device_uvector.hpp:579
size_type size() const noexcept
The number of elements in the vector.
Definition: device_uvector.hpp:564
const_pointer data() const noexcept
Returns const pointer to underlying device storage.
Definition: device_uvector.hpp:435
void resize(size_type new_size, cuda_stream_view stream)
Resizes the vector to contain new_size elements.
Definition: device_uvector.hpp:385
void set_element(size_type element_index, T const &value, cuda_stream_view stream)
Performs a synchronous copy of v to the specified element in device memory.
Definition: device_uvector.hpp:287
reverse_iterator rbegin() noexcept
Returns a reverse_iterator to the last element.
Definition: device_uvector.hpp:504
pointer data() noexcept
Returns pointer to underlying device storage.
Definition: device_uvector.hpp:425
void shrink_to_fit(cuda_stream_view stream)
Forces deallocation of unused device memory.
Definition: device_uvector.hpp:397
iterator end() noexcept
Returns an iterator to the element following the last element of the vector.
Definition: device_uvector.hpp:475
std::size_t size_type
The type used for the size of the vector.
Definition: device_uvector.hpp:76
const_reverse_iterator crbegin() const noexcept
Returns a const_reverse_iterator to the last element.
Definition: device_uvector.hpp:513
size_type capacity() const noexcept
Returns the number of elements that can be held in currently allocated storage.
Definition: device_uvector.hpp:412
std::int64_t ssize() const noexcept
The signed number of elements in the vector.
Definition: device_uvector.hpp:569
T value_type
Stored value type.
Definition: device_uvector.hpp:75
const_iterator cbegin() const noexcept
Returns a const_iterator to the first element.
Definition: device_uvector.hpp:456
value_type back_element(cuda_stream_view stream) const
Returns the last element.
Definition: device_uvector.hpp:343
const_pointer const_iterator
The type of the const iterator returned by cbegin()
Definition: device_uvector.hpp:83
device_buffer release() noexcept
Release ownership of device memory storage.
Definition: device_uvector.hpp:404
void set_element_to_zero_async(size_type element_index, cuda_stream_view stream)
Asynchronously sets the specified element to zero in device memory.
Definition: device_uvector.hpp:250
device_uvector(device_uvector &&) noexcept=default
Default move constructor.
pointer iterator
The type of the iterator returned by begin()
Definition: device_uvector.hpp:82
void reserve(size_type new_capacity, cuda_stream_view stream)
Increases the capacity of the vector to new_capacity elements.
Definition: device_uvector.hpp:362
value_type & reference
Reference type returned by operator[](size_type)
Definition: device_uvector.hpp:77
const_reverse_iterator rend() const noexcept
Returns const_reverse_iterator to the element preceding the first element of the vector.
Definition: device_uvector.hpp:559
const_iterator end() const noexcept
Returns an iterator to the element following the last element of the vector.
Definition: device_uvector.hpp:495
pointer element_ptr(size_type element_index) noexcept
Returns pointer to the specified element.
Definition: device_uvector.hpp:163
value_type front_element(cuda_stream_view stream) const
Returns the first element.
Definition: device_uvector.hpp:327
value_type const * const_pointer
The type of the pointer returned by data() const.
Definition: device_uvector.hpp:81
device_uvector(device_uvector const &other, cuda_stream_view stream, cuda::mr::any_resource< cuda::mr::device_accessible > mr=mr::get_current_device_resource_ref())
Construct a new device_uvector by deep copying the contents of another device_uvector.
Definition: device_uvector.hpp:147
value_type const & const_reference
Constant reference type returned by operator[](size_type) const.
Definition: device_uvector.hpp:79
const_reverse_iterator rbegin() const noexcept
Returns a const_reverse_iterator to the last element.
Definition: device_uvector.hpp:525
value_type element(size_type element_index, cuda_stream_view stream) const
Returns the specified element from device memory.
Definition: device_uvector.hpp:305
const_pointer element_ptr(size_type element_index) const noexcept
Returns pointer to the specified element.
Definition: device_uvector.hpp:177
cuda::std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: device_uvector.hpp:88
const_iterator begin() const noexcept
Returns a const_iterator to the first element.
Definition: device_uvector.hpp:465
iterator begin() noexcept
Returns an iterator to the first element.
Definition: device_uvector.hpp:447
Exception thrown when an argument to a function is invalid.
Definition: error.hpp:108
Exception thrown when attempting to access outside of a defined range.
Definition: error.hpp:99
device_async_resource_ref get_current_device_resource_ref()
Get the device_async_resource_ref for the current device.
Definition: per_device_resource.hpp:187
cuda::mr::resource_ref< cuda::mr::device_accessible > device_async_resource_ref
Alias for a cuda::mr::resource_ref with the property cuda::mr::device_accessible.
Definition: resource_ref.hpp:30
Management of per-device memory resources.