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 (owning_ and free_using_stream_) {
68  stream().enqueue.free(ptr_);
69  }
70  else {
71  device::free(ptr_);
72  }
73  }
74 
75 public: // operators
76 
77  imported_ptr_t(const imported_ptr_t& other) = delete;
78  imported_ptr_t& operator=(const imported_ptr_t& other) = delete;
79  imported_ptr_t& operator=(imported_ptr_t&& other) noexcept
80  {
81  ::std::swap(device_id_, other.device_id_);
82  ::std::swap(context_handle_, other.context_handle_);
83  ::std::swap(pool_handle_, other.pool_handle_);
84  ::std::swap(ptr_, other.ptr_);
85  ::std::swap(stream_handle_, other.stream_handle_);
86  ::std::swap(free_using_stream_, other.free_using_stream_);
87  ::std::swap(owning_, other.owning_);
88  return *this;
89  }
90  imported_ptr_t(imported_ptr_t&& other) noexcept = default;
91 
92 public: // getters
93 
94  template <typename T = void>
95  T* get() const noexcept
96  {
97  // If you're wondering why this cast is necessary - some IDEs/compilers
98  // have the notion that if the method is const, `ptr_` is a const void* within it
99  return static_cast<T*>(const_cast<void*>(ptr_));
100  }
101  stream_t stream() const
102  {
103  if (not free_using_stream_) throw ::std::runtime_error(
104  "Request of the freeing stream of an imported pointer"
105  "which is not to be freed on a stream.");
106  return stream::wrap(device_id_, context_handle_, stream_handle_);
107  }
108  pool_t pool() noexcept
109  {
110  static constexpr bool non_owning { false };
111  return memory::pool::wrap(device_id_, pool_handle_, non_owning);
112  }
113 
114 protected: // data members
115  cuda::device::id_t device_id_;
116  context::handle_t context_handle_;
117  pool::handle_t pool_handle_;
118  void* ptr_;
119  stream::handle_t stream_handle_;
120  bool free_using_stream_;
121  bool owning_;
122 }; // class imported_ptr_t
123 
124 inline imported_ptr_t wrap(
125  cuda::device::id_t device_id,
126  context::handle_t context_handle,
127  pool::handle_t pool_handle,
128  void * ptr,
129  stream::handle_t stream_handle,
130  bool free_using_stream,
131  bool owning) noexcept
132 {
133  return imported_ptr_t { device_id, context_handle, pool_handle, ptr, stream_handle, free_using_stream, owning };
134 }
135 
136 inline imported_ptr_t import_ptr(const pool_t& shared_pool, const ptr_handle_t& ptr_handle, const stream_t& freeing_stream)
137 {
138  constexpr const auto free_using_stream { true };
139  assert(shared_pool.device_id() == freeing_stream.device_id());
140  void* raw_ptr = detail_::import_ptr(shared_pool.handle(), ptr_handle);
141  static constexpr const bool is_owning { true };
142  return wrap(
143  shared_pool.device_id(),
144  freeing_stream.context_handle(),
145  shared_pool.handle(),
146  raw_ptr,
147  freeing_stream.handle(),
148  free_using_stream,
149  is_owning);
150 }
151 
152 inline imported_ptr_t import_ptr(const pool_t& shared_pool, const ptr_handle_t& ptr_handle)
153 {
154  constexpr const auto free_using_stream { false };
155  auto free_without_using_stream = static_cast<bool>(free_using_stream);
156  void* raw_ptr = detail_::import_ptr(shared_pool.handle(), ptr_handle);
157  static constexpr const bool is_owning { true };
158  return wrap(
159  shared_pool.device_id(),
160  context::detail_::none,
161  shared_pool.handle(),
162  raw_ptr,
164  free_without_using_stream,
165  is_owning);
166 }
167 
168 } // namespace ipc
169 
170 } // namespace pool
171 
172 } // namespace memory
173 
174 } // namespace cuda
175 
176 #endif // CUDA_VERSION >= 11020
177 
178 #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:850
void free(void *ptr)
Free a region of device-side memory (regardless of how it was allocated)
Definition: memory.hpp:130
CUipcEventHandle handle_t
The concrete value passed between processes, used to tell the CUDA Runtime API which event is desired...
Definition: ipc.hpp:260
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:1006
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:264
CUstream handle_t
The CUDA driver&#39;s raw handle for streams.
Definition: types.hpp:239
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