cuda-api-wrappers
Thin C++-flavored wrappers for the CUDA Runtime API
external.hpp
Go to the documentation of this file.
1 
8 #pragma once
9 #ifndef CUDA_API_WRAPPERS_EXTERNAL_HPP_
10 #define CUDA_API_WRAPPERS_EXTERNAL_HPP_
11 
12 #if CUDA_VERSION >= 10000
13 
14 #include "memory.hpp"
15 #include "unique_region.hpp"
16 
17 namespace cuda {
18 
19 namespace memory {
20 
22 namespace external {
23 
24 enum kind_t : ::std::underlying_type<CUexternalMemoryHandleType_enum>::type {
25  opaque_file_descriptor = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD,
26  opaque_shared_windows_handle = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32,
27  opaque_globally_shared_windows_handle = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT,
28  direct3d_12_heap = CU_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP,
29  direct3d_12_committed_resource = CU_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE,
30 #if CUDA_VERSION >= 10200
31  direct3d_resource_shared_windows_handle = CU_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_RESOURCE,
32  direct3d_resource_globally_shared_handle = CU_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_RESOURCE_KMT,
33  nvscibuf_object = CU_EXTERNAL_MEMORY_HANDLE_TYPE_NVSCIBUF
34 #endif // CUDA_VERSION >= 10200
35 };
36 
38 using descriptor_t = CUDA_EXTERNAL_MEMORY_HANDLE_DESC;
39 
40 namespace detail_ {
41 
42 inline void destroy(handle_t handle, const descriptor_t &)
43 {
44  auto status = cuDestroyExternalMemory(handle);
45  throw_if_error_lazy(status, ::std::string("Destroying a memory resource"));
46 }
47 
48 inline ::std::string identify(subregion_spec_t subregion_spec)
49 {
50  return "subregion of size " + ::std::to_string(subregion_spec.size)
51  + " at offset " + ::std::to_string(subregion_spec.offset);
52 }
53 
54 inline ::std::string identify(handle_t handle)
55 {
56  return "external memory resource at " + cuda::detail_::ptr_as_hex(handle);
57 }
58 
59 inline ::std::string identify(descriptor_t descriptor)
60 {
61  return "external memory resource of kind " + ::std::to_string(descriptor.type);
62 }
63 
64 inline ::std::string identify(handle_t handle, descriptor_t descriptor)
65 {
66  return "external memory resource of kind " + ::std::to_string(descriptor.type)
67  + " at " + cuda::detail_::ptr_as_hex(handle);
68 }
69 
70 inline handle_t import(const descriptor_t& descriptor)
71 {
72  handle_t handle;
73  auto status = cuImportExternalMemory(&handle, &descriptor);
74  throw_if_error_lazy(status, "Failed importing " + identify(descriptor));
75  return handle;
76 }
77 
78 } // namespace detail_
79 
81 class resource_t;
83 
85 resource_t wrap(handle_t handle, descriptor_t descriptor, bool take_ownership = false);
86 
91 class resource_t {
92 public:
93  friend resource_t wrap(handle_t handle, descriptor_t descriptor, bool take_ownership);
94 
95  handle_t handle() const { return handle_; }
96  descriptor_t descriptor() const { return descriptor_; }
97  kind_t kind() const { return static_cast<kind_t>(descriptor_.type); }
98  size_t size() const { return descriptor_.size; }
99 
100 protected:
101 
102  resource_t(handle_t handle, descriptor_t descriptor, bool is_owning)
103  : handle_(handle), descriptor_(descriptor), owning_(is_owning)
104  {}
105 
106 public:
107  resource_t(const resource_t& other) = delete;
108 
109  resource_t(resource_t&& other) noexcept : resource_t(
110  other.handle_, other.descriptor_, other.owning_)
111  {
112  other.owning_ = false;
113  };
114 
115  ~resource_t()
116  {
117  if (owning_) {
118 #ifdef NDEBUG
119  cuDestroyExternalMemory(handle_);
120  // Note: "Swallowing" any potential error to avoid ::std::terminate()
121 #else
122  detail_::destroy(handle_, descriptor_);
123 #endif
124  }
125  }
126 
127 protected: // data members
128  handle_t handle_;
129  descriptor_t descriptor_;
130  bool owning_;
131 };
132 
133 inline resource_t wrap(handle_t handle, descriptor_t descriptor, bool take_ownership)
134 {
135  return { handle, ::std::move(descriptor), take_ownership };
136 }
137 
139 inline resource_t import(descriptor_t descriptor)
140 {
141  handle_t handle = detail_::import(descriptor);
142  return wrap(handle, descriptor, do_take_ownership);
143 }
144 
145 namespace detail_ {
146 
147 inline region_t map(handle_t handle, subregion_spec_t subregion)
148 {
150  CUDA_EXTERNAL_MEMORY_BUFFER_DESC_st buffer_desc;
151  buffer_desc.flags = 0u;
152  buffer_desc.offset = subregion.offset;
153  buffer_desc.size = subregion.size;
154  auto result = cuExternalMemoryGetMappedBuffer(&address, handle, &buffer_desc);
155  throw_if_error_lazy(result, "Failed mapping " + detail_::identify(subregion)
156  + " within " + detail_::identify(handle) + " to a device buffer");
157  return region_t{as_pointer(address), subregion.size};
158 }
159 
160 } // namespace detail_
161 
164 using unique_region = memory::unique_region<device::detail_::deleter>;
165 
167 inline unique_region wrap(region_t mapped_region)
168 {
169  return unique_region{ mapped_region };
170 }
171 
173 inline unique_region map(const resource_t& resource, subregion_spec_t subregion_to_map)
174 {
175  auto mapped_region = detail_::map(resource.handle(), subregion_to_map);
176  return wrap(mapped_region);
177 }
178 
180 inline unique_region map(const resource_t& resource)
181 {
182  auto subregion_spec = subregion_spec_t { 0u, resource.size() };
183  return map(resource, subregion_spec);
184 }
185 
186 // Note: mapping mipmapped arrays currently not supported
187 
188 } // namespace external
189 } // namespace memory
190 } // namespace cuda
191 
192 #endif // CUDA_VERSION >= 10000
193 
194 #endif // CUDA_API_WRAPPERS_EXTERNAL_HPP_
typename ::std::conditional< NumDimensions==2, CUDA_ARRAY_DESCRIPTOR, CUDA_ARRAY3D_DESCRIPTOR >::type descriptor_t
Raw CUDA driver descriptor structure for an array of dimension.
Definition: array.hpp:38
Definitions and functionality wrapping CUDA APIs.
Definition: array.hpp:22
memory::unique_region< detail_::deleter > unique_region
A unique region of device-global memory.
Definition: unique_region.hpp:153
detail_::region_helper< memory::region_t > region_t
A child class of the generic region_t with some managed-memory-specific functionality.
Definition: memory.hpp:1960
#define throw_if_error_lazy(status__,...)
A macro for only throwing an error if we&#39;ve failed - which also ensures no string is constructed unle...
Definition: error.hpp:316
CUarray handle_t
Raw CUDA driver handle for arrays (of any dimension)
Definition: array.hpp:34
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
address_t address(const void *device_ptr) noexcept
Definition: types.hpp:682
void * as_pointer(device::address_t address) noexcept
Definition: types.hpp:700
CUdeviceptr address_t
The numeric type which can represent the range of memory addresses on a CUDA device.
Definition: types.hpp:672