device_scalar.hpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #pragma once
7 
8 #include <rmm/detail/export.hpp>
9 #include <rmm/device_uvector.hpp>
11 #include <rmm/resource_ref.hpp>
12 
13 #include <cuda/stream>
14 
15 #include <type_traits>
16 
17 RMM_NAMESPACE_BEGIN
31 template <typename T>
33  public:
34  static_assert(std::is_trivially_copyable_v<T>, "Scalar type must be trivially copyable");
35 
40  using pointer =
44 
45  RMM_EXEC_CHECK_DISABLE
46  ~device_scalar() = default;
47 
48  RMM_EXEC_CHECK_DISABLE
49  device_scalar(device_scalar&&) noexcept = default;
50 
56  device_scalar& operator=(device_scalar&&) noexcept = default;
57 
61  device_scalar(device_scalar const&) = delete;
62 
66  device_scalar& operator=(device_scalar const&) = delete;
67 
71  device_scalar() = delete;
72 
87  explicit device_scalar(
88  cuda::stream_ref stream,
89  cuda::mr::any_resource<cuda::mr::device_accessible> mr = mr::get_current_device_resource_ref())
90  : _storage{1, stream, std::move(mr)}
91  {
92  }
93 
112  explicit device_scalar(
113  value_type const& initial_value,
114  cuda::stream_ref stream,
115  cuda::mr::any_resource<cuda::mr::device_accessible> mr = mr::get_current_device_resource_ref())
116  : _storage{1, stream, std::move(mr)}
117  {
118  set_value_async(initial_value, stream);
119  }
120 
121  // Disallow passing literals to the constructor to avoid race conditions where the
122  // memory holding the literal can be freed before the async memcpy / memset executes.
123  device_scalar(value_type const&&,
124  cuda::stream_ref stream,
125  cuda::mr::any_resource<cuda::mr::device_accessible> mr =
140  device_scalar const& other,
141  cuda::stream_ref stream,
142  cuda::mr::any_resource<cuda::mr::device_accessible> mr = mr::get_current_device_resource_ref())
143  : _storage{other._storage, stream, std::move(mr)}
144  {
145  }
146 
163  [[nodiscard]] value_type value(cuda::stream_ref stream) const
164  {
165  return _storage.front_element(stream);
166  }
167 
201  void set_value_async(value_type const& value, cuda::stream_ref stream)
202  {
203  _storage.set_element_async(0, value, stream);
204  }
205 
206  // Disallow passing literals to set_value to avoid race conditions where the memory holding the
207  // literal can be freed before the async memcpy / memset executes.
208  void set_value_async(value_type const&&, cuda::stream_ref) = delete;
209 
224  void set_value_to_zero_async(cuda::stream_ref stream)
225  {
226  _storage.set_element_to_zero_async(size_type{0}, stream);
227  }
228 
239  [[nodiscard]] pointer data() noexcept { return static_cast<pointer>(_storage.data()); }
240 
251  [[nodiscard]] const_pointer data() const noexcept
252  {
253  return static_cast<const_pointer>(_storage.data());
254  }
255 
259  [[nodiscard]] constexpr size_type size() const noexcept { return 1; }
260 
264  [[nodiscard]] cuda::stream_ref stream() const noexcept { return _storage.stream(); }
265 
271  void set_stream(cuda::stream_ref stream) noexcept { _storage.set_stream(stream); }
272 
273  private:
274  rmm::device_uvector<T> _storage;
275 };
276 
277 static_assert(std::is_constructible_v<device_scalar<int>, int const&, cuda::stream_ref>);
278 static_assert(std::is_constructible_v<device_scalar<int>,
279  int const&,
280  cuda::stream_ref,
281  cuda::mr::any_resource<cuda::mr::device_accessible>>);
282 static_assert(!std::is_constructible_v<device_scalar<int>, int, cuda::stream_ref>);
283 static_assert(!std::is_constructible_v<device_scalar<int>, int const, cuda::stream_ref>);
284 static_assert(!std::is_constructible_v<device_scalar<int>,
285  int,
286  cuda::stream_ref,
287  cuda::mr::any_resource<cuda::mr::device_accessible>>);
288 static_assert(!std::is_constructible_v<device_scalar<int>,
289  int const,
290  cuda::stream_ref,
291  cuda::mr::any_resource<cuda::mr::device_accessible>>);
292 static_assert([]<typename Scalar>(Scalar*) {
293  return requires(Scalar& scalar, int value, cuda::stream_ref stream) {
294  scalar.set_value_async(value, stream);
295  } && requires(Scalar& scalar, int const value, cuda::stream_ref stream) {
296  scalar.set_value_async(value, stream);
297  } && !requires(Scalar& scalar, int value, cuda::stream_ref stream) {
298  scalar.set_value_async(std::move(value), stream);
299  } && !requires(Scalar& scalar, int const value, cuda::stream_ref stream) {
300  scalar.set_value_async(std::move(value), stream);
301  };
302 }(static_cast<device_scalar<int>*>(nullptr)));
303  // end of group
305 RMM_NAMESPACE_END
Container for a single object of type T in device memory.
Definition: device_scalar.hpp:32
typename device_uvector< T >::value_type value_type
T, the type of the scalar element.
Definition: device_scalar.hpp:36
cuda::stream_ref stream() const noexcept
Stream associated with the device memory allocation.
Definition: device_scalar.hpp:264
void set_value_to_zero_async(cuda::stream_ref stream)
Sets the value of the device_scalar to zero on the specified stream.
Definition: device_scalar.hpp:224
constexpr size_type size() const noexcept
The size of the scalar: always 1.
Definition: device_scalar.hpp:259
device_scalar(value_type const &initial_value, cuda::stream_ref stream, cuda::mr::any_resource< cuda::mr::device_accessible > mr=mr::get_current_device_resource_ref())
Construct a new device_scalar with an initial value.
Definition: device_scalar.hpp:112
void set_value_async(value_type const &value, cuda::stream_ref stream)
Sets the value of the device_scalar to the value of v.
Definition: device_scalar.hpp:201
const_pointer data() const noexcept
Returns const pointer to object in device memory.
Definition: device_scalar.hpp:251
typename device_uvector< T >::const_reference const_reference
const value_type&
Definition: device_scalar.hpp:39
typename device_uvector< T >::size_type size_type
The type used for the size.
Definition: device_scalar.hpp:37
device_scalar(device_scalar &&) noexcept=default
Default move constructor.
typename device_uvector< T >::const_pointer const_pointer
Definition: device_scalar.hpp:43
value_type value(cuda::stream_ref stream) const
Copies the value from device to host, synchronizes, and returns the value.
Definition: device_scalar.hpp:163
pointer data() noexcept
Returns pointer to object in device memory.
Definition: device_scalar.hpp:239
device_scalar(device_scalar const &other, cuda::stream_ref stream, cuda::mr::any_resource< cuda::mr::device_accessible > mr=mr::get_current_device_resource_ref())
Construct a new device_scalar by deep copying the contents of another device_scalar,...
Definition: device_scalar.hpp:139
void set_stream(cuda::stream_ref stream) noexcept
Sets the stream to be used for deallocation.
Definition: device_scalar.hpp:271
typename device_uvector< T >::pointer pointer
The type of the pointer returned by data()
Definition: device_scalar.hpp:41
typename device_uvector< T >::reference reference
value_type&
Definition: device_scalar.hpp:38
An uninitialized vector of elements in device memory.
Definition: device_uvector.hpp:70
value_type * pointer
The type of the pointer returned by data()
Definition: device_uvector.hpp:80
std::size_t size_type
The type used for the size of the vector.
Definition: device_uvector.hpp:76
T value_type
Stored value type.
Definition: device_uvector.hpp:75
value_type & reference
Reference type returned by operator[](size_type)
Definition: device_uvector.hpp:77
value_type const * const_pointer
The type of the pointer returned by data() const.
Definition: device_uvector.hpp:81
value_type const & const_reference
Constant reference type returned by operator[](size_type) const.
Definition: device_uvector.hpp:79
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
Management of per-device memory resources.