cuda-api-wrappers
Thin C++-flavored wrappers for the CUDA Runtime API
ipc.hpp
Go to the documentation of this file.
1 
7 #pragma once
8 #ifndef MULTI_WRAPPER_IMPLS_IPC_HPP_
9 #define MULTI_WRAPPER_IMPLS_IPC_HPP_
10 
11 #if CUDA_VERSION >= 11020
12 
13 #include "../ipc.hpp"
14 #include "../stream.hpp"
15 #include "../memory_pool.hpp"
16 
17 namespace cuda {
18 
19 namespace memory {
20 
21 namespace pool {
22 
23 namespace ipc {
24 
25 class imported_ptr_t;
26 
27 imported_ptr_t wrap(
28  cuda::device::id_t device_id,
29  context::handle_t context_handle,
30  pool::handle_t pool_handle,
31  void * ptr,
32  stream::handle_t stream_handle,
33  bool free_using_stream,
34  bool owning) noexcept;
35 
36 class imported_ptr_t {
37 protected: // constructors & destructor
38  imported_ptr_t(
39  cuda::device::id_t device_id,
40  context::handle_t context_handle,
41  pool::handle_t pool_handle,
42  void * ptr,
43  stream::handle_t stream_handle,
44  bool free_using_stream,
45  bool owning) noexcept
46  :
47  device_id_(device_id),
48  context_handle_(context_handle),
49  pool_handle_(pool_handle),
50  ptr_(ptr),
51  stream_handle_(stream_handle),
52  free_using_stream_(free_using_stream),
53  owning_(owning) { }
54 
55 public: // constructors & destructor
56  friend imported_ptr_t wrap(
57  cuda::device::id_t device_id,
58  context::handle_t context_handle,
59  pool::handle_t pool_handle,
60  void * ptr,
61  stream::handle_t stream_handle,
62  bool free_using_stream,
63  bool owning) noexcept;
64 
65  ~imported_ptr_t() noexcept(false)
66  {
67  if (not owning_) { return; }
68 #ifdef THROW_IN_DESTRUCTORS
69  try
70 #endif
71  {
72  if (free_using_stream_) {
73  stream().enqueue.free(ptr_);
74  }
75  else {
76  device::free(ptr_);
77  }
78  }
79 #ifdef THROW_IN_DESTRUCTORS
80  catch (...) {}
81 #endif
82  }
83 
84 public: // operators
85 
86  imported_ptr_t(const imported_ptr_t& other) = delete;
87  imported_ptr_t& operator=(const imported_ptr_t& other) = delete;
88  imported_ptr_t& operator=(imported_ptr_t&& other) noexcept
89  {
90  ::std::swap(device_id_, other.device_id_);
91  ::std::swap(context_handle_, other.context_handle_);
92  ::std::swap(pool_handle_, other.pool_handle_);
93  ::std::swap(ptr_, other.ptr_);
94  ::std::swap(stream_handle_, other.stream_handle_);
95  ::std::swap(free_using_stream_, other.free_using_stream_);
96  ::std::swap(owning_, other.owning_);
97  return *this;
98  }
99  imported_ptr_t(imported_ptr_t&& other) noexcept = default;
100 
101 public: // getters
102 
103  template <typename T = void>
104  T* get() const noexcept
105  {
106  // If you're wondering why this cast is necessary - some IDEs/compilers
107  // have the notion that if the method is const, `ptr_` is a const void* within it
108  return static_cast<T*>(const_cast<void*>(ptr_));
109  }
110  stream_t stream() const
111  {
112  if (not free_using_stream_) throw ::std::runtime_error(
113  "Request of the freeing stream of an imported pointer"
114  "which is not to be freed on a stream.");
115  return stream::wrap(device_id_, context_handle_, stream_handle_);
116  }
117  pool_t pool() noexcept
118  {
119  static constexpr bool non_owning { false };
120  return memory::pool::wrap(device_id_, pool_handle_, non_owning);
121  }
122 
123 protected: // data members
124  cuda::device::id_t device_id_;
125  context::handle_t context_handle_;
126  pool::handle_t pool_handle_;
127  void* ptr_;
128  stream::handle_t stream_handle_;
129  bool free_using_stream_;
130  bool owning_;
131 }; // class imported_ptr_t
132 
133 inline imported_ptr_t wrap(
134  cuda::device::id_t device_id,
135  context::handle_t context_handle,
136  pool::handle_t pool_handle,
137  void * ptr,
138  stream::handle_t stream_handle,
139  bool free_using_stream,
140  bool owning) noexcept
141 {
142  return imported_ptr_t { device_id, context_handle, pool_handle, ptr, stream_handle, free_using_stream, owning };
143 }
144 
145 inline imported_ptr_t import_ptr(const pool_t& shared_pool, const ptr_handle_t& ptr_handle, const stream_t& freeing_stream)
146 {
147  constexpr const auto free_using_stream { true };
148  assert(shared_pool.device_id() == freeing_stream.device_id());
149  void* raw_ptr = detail_::import_ptr(shared_pool.handle(), ptr_handle);
150  static constexpr const bool is_owning { true };
151  return wrap(
152  shared_pool.device_id(),
153  freeing_stream.context_handle(),
154  shared_pool.handle(),
155  raw_ptr,
156  freeing_stream.handle(),
157  free_using_stream,
158  is_owning);
159 }
160 
161 inline imported_ptr_t import_ptr(const pool_t& shared_pool, const ptr_handle_t& ptr_handle)
162 {
163  constexpr const auto free_using_stream { false };
164  auto free_without_using_stream = static_cast<bool>(free_using_stream);
165  void* raw_ptr = detail_::import_ptr(shared_pool.handle(), ptr_handle);
166  static constexpr const bool is_owning { true };
167  return wrap(
168  shared_pool.device_id(),
169  context::detail_::none,
170  shared_pool.handle(),
171  raw_ptr,
173  free_without_using_stream,
174  is_owning);
175 }
176 
177 } // namespace ipc
178 
179 } // namespace pool
180 
181 } // namespace memory
182 
183 } // namespace cuda
184 
185 #endif // CUDA_VERSION >= 11020
186 
187 #endif //CUDA_API_WRAPPERS_IPC_HPP
Definitions and functionality wrapping CUDA APIs.
Definition: array.hpp:22
CUdevice id_t
Numeric ID of a CUDA device used by the CUDA Runtime API.
Definition: types.hpp:852
void free(void *ptr)
Free a region of device-side memory (regardless of how it was allocated)
Definition: memory.hpp:126
CUipcEventHandle handle_t
The concrete value passed between processes, used to tell the CUDA Runtime API which event is desired...
Definition: ipc.hpp:276
stream_t wrap(device::id_t device_id, context::handle_t context_handle, handle_t stream_handle, bool take_ownership=false, bool hold_pc_refcount_unit=false) noexcept
Wrap an existing stream in a stream_t instance.
Definition: stream.hpp:1020
array_t< T, NumDimensions > wrap(device::id_t device_id, context::handle_t context_handle, handle_t handle, dimensions_t< NumDimensions > dimensions) noexcept
Wrap an existing CUDA array in an array_t instance.
Definition: array.hpp:271
CUstream handle_t
The CUDA driver&#39;s raw handle for streams.
Definition: types.hpp:236
const stream::handle_t default_stream_handle
The CUDA runtime provides a default stream on which work is scheduled when no stream is specified; fo...
Definition: constants.hpp:42