pinned_memory_resource.hpp
1 
5 #pragma once
6 
7 #include <cstddef>
8 #include <memory>
9 #include <optional>
10 
11 #include <cuda.h>
12 #include <cuda_runtime_api.h>
13 
14 #include <cuda/memory_resource>
15 
16 #include <rmm/aligned.hpp>
17 #include <rmm/cuda_device.hpp>
18 #include <rmm/cuda_stream_view.hpp>
19 #include <rmm/device_buffer.hpp>
20 
21 #include <rapidsmpf/config.hpp>
22 #include <rapidsmpf/detail/rmm_resource_adaptor_impl.hpp>
23 #include <rapidsmpf/error.hpp>
24 #include <rapidsmpf/memory/back_ref_mixin.hpp>
25 #include <rapidsmpf/system_info.hpp>
26 #include <rapidsmpf/utils/misc.hpp>
27 
29 // NOLINTBEGIN(modernize-macro-to-enum)
30 #define RAPIDSMPF_PINNED_MEM_RES_MIN_CUDA_VERSION 12060
31 #define RAPIDSMPF_PINNED_MEM_RES_MIN_CUDA_VERSION_STR "v12.6"
32 
33 // NOLINTEND(modernize-macro-to-enum)
34 
35 namespace rapidsmpf {
36 
37 class BufferResource;
38 
48  static const bool supported = [] {
49  // check if the device supports async memory pools
50  int cuda_pool_supported{};
51  auto attr_result = cudaDeviceGetAttribute(
52  &cuda_pool_supported,
53  cudaDevAttrMemoryPoolsSupported,
55  );
56  if (attr_result != cudaSuccess || cuda_pool_supported != 1) {
57  return false;
58  }
59 
60  int cuda_driver_version{};
61  auto driver_result = cudaDriverGetVersion(&cuda_driver_version);
62  int cuda_runtime_version{};
63  auto runtime_result = cudaRuntimeGetVersion(&cuda_runtime_version);
64  return driver_result == cudaSuccess && runtime_result == cudaSuccess
65  && cuda_driver_version >= RAPIDSMPF_PINNED_MEM_RES_MIN_CUDA_VERSION
66  && cuda_runtime_version >= RAPIDSMPF_PINNED_MEM_RES_MIN_CUDA_VERSION;
67  }();
68  return supported;
69 }
70 
78  std::size_t initial_pool_size = 0;
79 
81  std::optional<std::size_t> max_pool_size = std::nullopt;
82 
86 };
87 
94 inline constexpr std::optional<PinnedPoolProperties> PinnedMemoryDisabled{};
95 
112 std::optional<PinnedPoolProperties> pinned_pool_properties_from_options(
113  config::Options options
114 );
115 
129  : public cuda::mr::shared_resource<
130  detail::RmmResourceAdaptorImpl<cuda::pinned_memory_pool>>,
131  public BackRefMixin<BufferResource> {
132  using shared_base = cuda::mr::shared_resource<
134 
135  public:
148  [[nodiscard]] void* allocate(
149  cuda::stream_ref stream,
150  std::size_t size,
151  std::size_t alignment = rmm::CUDA_ALLOCATION_ALIGNMENT
152  ) {
153  return get().allocate(stream, size, alignment);
154  }
155 
165  cuda::stream_ref stream,
166  void* ptr,
167  std::size_t size,
168  std::size_t alignment = rmm::CUDA_ALLOCATION_ALIGNMENT
169  ) noexcept {
170  get().deallocate(stream, ptr, size, alignment);
171  }
172 
179  [[nodiscard]] bool operator==(PinnedMemoryResource const& other) const noexcept {
180  return get() == other.get();
181  }
182 
188  [[nodiscard]] std::int64_t current_allocated() const noexcept {
189  return get().current_allocated();
190  }
191 
198  return get().get_main_record();
199  }
200 
206  [[nodiscard]] constexpr PinnedPoolProperties const& properties() const noexcept {
207  return pool_properties_;
208  }
209 
213  friend void get_property(
214  PinnedMemoryResource const&, cuda::mr::host_accessible
215  ) noexcept {}
216 
217  private:
228  explicit PinnedMemoryResource(PinnedPoolProperties pool_properties);
229 
230  friend class BufferResource;
231 
232  PinnedPoolProperties pool_properties_;
233 };
234 
235 static_assert(cuda::mr::resource<PinnedMemoryResource>);
236 static_assert(cuda::mr::resource_with<PinnedMemoryResource, cuda::mr::host_accessible>);
237 static_assert(cuda::mr::resource_with<PinnedMemoryResource, cuda::mr::device_accessible>);
238 
239 } // namespace rapidsmpf
Mixin that lets copies of the this object keep an external object reference of type BackRef alive.
Class managing buffer resources.
Memory resource that provides pinned (page-locked) host memory using a pool.
ScopedMemoryRecord get_main_memory_record() const
Returns the main memory record for the pinned pool.
std::int64_t current_allocated() const noexcept
Returns the total number of currently allocated bytes.
bool operator==(PinnedMemoryResource const &other) const noexcept
Equality comparison.
void * allocate(cuda::stream_ref stream, std::size_t size, std::size_t alignment=rmm::CUDA_ALLOCATION_ALIGNMENT)
Allocates pinned host memory associated with a CUDA stream.
constexpr PinnedPoolProperties const & properties() const noexcept
Returns the properties used to configure the pool.
void deallocate(cuda::stream_ref stream, void *ptr, std::size_t size, std::size_t alignment=rmm::CUDA_ALLOCATION_ALIGNMENT) noexcept
Deallocates pinned host memory associated with a CUDA stream.
friend void get_property(PinnedMemoryResource const &, cuda::mr::host_accessible) noexcept
Enables the cuda::mr::host_accessible property.
Manages configuration options for RapidsMPF operations.
Definition: config.hpp:144
Implementation class for RmmResourceAdaptor.
cuda_device_id get_current_cuda_device()
static constexpr std::size_t CUDA_ALLOCATION_ALIGNMENT
RAPIDS Multi-Processor interfaces.
Definition: backend.hpp:14
std::optional< PinnedPoolProperties > pinned_pool_properties_from_options(config::Options options)
Parse pinned memory pool properties from configuration options.
constexpr std::optional< PinnedPoolProperties > PinnedMemoryDisabled
Sentinel used to disable pinned host memory.
bool is_pinned_memory_resources_supported()
Checks if the PinnedMemoryResource is supported for the current CUDA version.
int get_current_numa_node() noexcept
Get the NUMA node ID associated with the calling CPU thread.
Properties for configuring a pinned memory pool.
int numa_id
NUMA node from which pinned memory should be allocated. Defaults to the NUMA node of the calling thre...
std::optional< std::size_t > max_pool_size
Maximum size of the pool. std::nullopt means no limit.
std::size_t initial_pool_size
Initial size of the pool. Initial size is important for pinned memory performance,...
Memory statistics for a specific scope.