cuda-api-wrappers
Thin C++-flavored wrappers for the CUDA Runtime API
external.hpp
Go to the documentation of this file.
1 
9 #pragma once
10 #ifndef CUDA_API_WRAPPERS_EXTERNAL_HPP_
11 #define CUDA_API_WRAPPERS_EXTERNAL_HPP_
12 
13 #if CUDA_VERSION >= 10000
14 
15 #include "memory.hpp"
16 #include "unique_region.hpp"
17 
18 namespace cuda {
19 
20 namespace memory {
21 
23 namespace external {
24 
25 enum kind_t : ::std::underlying_type<CUexternalMemoryHandleType_enum>::type {
26  opaque_file_descriptor = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD,
27  opaque_shared_windows_handle = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32,
28  opaque_globally_shared_windows_handle = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT,
29  direct3d_12_heap = CU_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP,
30  direct3d_12_committed_resource = CU_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE,
31 #if CUDA_VERSION >= 10200
32  direct3d_resource_shared_windows_handle = CU_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_RESOURCE,
33  direct3d_resource_globally_shared_handle = CU_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_RESOURCE_KMT,
34  nvscibuf_object = CU_EXTERNAL_MEMORY_HANDLE_TYPE_NVSCIBUF
35 #endif // CUDA_VERSION >= 10200
36 };
37 
39 using descriptor_t = CUDA_EXTERNAL_MEMORY_HANDLE_DESC;
40 
41 namespace detail_ {
42 
43 // TODO: Isn't this contextualized? I wonder
44 inline status_t destroy_nowthrow(handle_t handle)
45 {
46  return cuDestroyExternalMemory(handle);
47 }
48 
49 
50 inline void destroy(handle_t handle, const descriptor_t &)
51 {
52  auto status = destroy_nowthrow(handle);
53  throw_if_error_lazy(status, ::std::string("Destroying a memory resource"));
54 }
55 
56 inline ::std::string identify(subregion_spec_t subregion_spec)
57 {
58  return "subregion of size " + ::std::to_string(subregion_spec.size)
59  + " at offset " + ::std::to_string(subregion_spec.offset);
60 }
61 
62 inline ::std::string identify(handle_t handle)
63 {
64  return "external memory resource at " + cuda::detail_::ptr_as_hex(handle);
65 }
66 
67 inline ::std::string identify(descriptor_t descriptor)
68 {
69  return "external memory resource of kind " + ::std::to_string(descriptor.type);
70 }
71 
72 inline ::std::string identify(handle_t handle, descriptor_t descriptor)
73 {
74  return "external memory resource of kind " + ::std::to_string(descriptor.type)
75  + " at " + cuda::detail_::ptr_as_hex(handle);
76 }
77 
78 inline handle_t import(const descriptor_t& descriptor)
79 {
80  handle_t handle;
81  auto status = cuImportExternalMemory(&handle, &descriptor);
82  throw_if_error_lazy(status, "Failed importing " + identify(descriptor));
83  return handle;
84 }
85 
86 } // namespace detail_
87 
89 class resource_t;
91 
93 resource_t wrap(handle_t handle, descriptor_t descriptor, bool take_ownership = false);
94 
99 class resource_t {
100 public:
101  friend resource_t wrap(handle_t handle, descriptor_t descriptor, bool take_ownership);
102 
103  handle_t handle() const { return handle_; }
104  descriptor_t descriptor() const { return descriptor_; }
105  kind_t kind() const { return static_cast<kind_t>(descriptor_.type); }
106  size_t size() const { return descriptor_.size; }
107 
108 protected:
109 
110  resource_t(handle_t handle, descriptor_t descriptor, bool is_owning)
111  : handle_(handle), descriptor_(descriptor), owning_(is_owning)
112  {}
113 
114 public:
115  resource_t(const resource_t& other) = delete;
116 
117  resource_t(resource_t&& other) noexcept : resource_t(
118  other.handle_, other.descriptor_, other.owning_)
119  {
120  other.owning_ = false;
121  };
122 
123  ~resource_t() DESTRUCTOR_EXCEPTION_SPEC
124  {
125  if (not owning_) { return; }
126 #if THROW_IN_DESTRUCTORS
127  detail_::destroy(handle_, descriptor_);
128 #else
129  detail_::destroy(handle_, descriptor_);
130 #endif
131  }
132 
133 protected: // data members
134  handle_t handle_;
135  descriptor_t descriptor_;
136  bool owning_;
137 };
138 
139 inline resource_t wrap(handle_t handle, descriptor_t descriptor, bool take_ownership)
140 {
141  return { handle, ::std::move(descriptor), take_ownership };
142 }
143 
145 inline resource_t import(descriptor_t descriptor)
146 {
147  handle_t handle = detail_::import(descriptor);
148  return wrap(handle, descriptor, do_take_ownership);
149 }
150 
151 namespace detail_ {
152 
153 inline region_t map(handle_t handle, subregion_spec_t subregion)
154 {
156  CUDA_EXTERNAL_MEMORY_BUFFER_DESC_st buffer_desc;
157  buffer_desc.flags = 0u;
158  buffer_desc.offset = subregion.offset;
159  buffer_desc.size = subregion.size;
160  auto result = cuExternalMemoryGetMappedBuffer(&address, handle, &buffer_desc);
161  throw_if_error_lazy(result, "Failed mapping " + detail_::identify(subregion)
162  + " within " + detail_::identify(handle) + " to a device buffer");
163  return region_t{as_pointer(address), subregion.size};
164 }
165 
166 } // namespace detail_
167 
170 using unique_region = memory::unique_region<device::detail_::deleter>;
171 
173 inline unique_region wrap(region_t mapped_region)
174 {
175  return unique_region{ mapped_region };
176 }
177 
179 inline unique_region map(const resource_t& resource, subregion_spec_t subregion_to_map)
180 {
181  auto mapped_region = detail_::map(resource.handle(), subregion_to_map);
182  return wrap(mapped_region);
183 }
184 
186 inline unique_region map(const resource_t& resource)
187 {
188  auto subregion_spec = subregion_spec_t { 0u, resource.size() };
189  return map(resource, subregion_spec);
190 }
191 
192 } // namespace external
193 } // namespace memory
194 } // namespace cuda
195 
196 #endif // CUDA_VERSION >= 10000
197 
198 #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:1974
#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:327
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:271
address_t address(const void *device_ptr) noexcept
Definition: types.hpp:684
void * as_pointer(device::address_t address) noexcept
Definition: types.hpp:702
CUdeviceptr address_t
The numeric type which can represent the range of memory addresses on a CUDA device.
Definition: types.hpp:674
CUresult status_t
Indicates either the result (success or error index) of a CUDA Runtime or Driver API call...
Definition: types.hpp:74