cuda-api-wrappers
Thin C++-flavored wrappers for the CUDA Runtime API
node.hpp
Go to the documentation of this file.
1 
6 #pragma once
7 #ifndef CUDA_API_WRAPPERS_NODE_HPP
8 #define CUDA_API_WRAPPERS_NODE_HPP
9 
10 #if CUDA_VERSION >= 10000
11 
12 #include "../types.hpp"
13 #include "identify.hpp"
14 
15 namespace cuda {
16 
17 namespace graph {
18 
20 class node_t;
21 class template_t;
22 class instance_t;
24 
25 namespace node {
26 
27 node_t wrap(template_::handle_t graph_handle, handle_t handle) noexcept;
28 
29 namespace detail_ {
30 
31 ::std::string identify(const node_t &node);
32 
33 inline status_t get_dependencies(
34  handle_t handle,
35  handle_t * __restrict__ dependency_handles,
36  ::std::size_t * __restrict__ num_dependencies)
37 {
38 #if CUDA_VERSION >= 13000
39  static constexpr auto no_edge_data { nullptr };
40  return cuGraphNodeGetDependencies(handle, dependency_handles, no_edge_data, num_dependencies);
41 #else
42  return cuGraphNodeGetDependencies(handle, dependency_handles, num_dependencies);
43 #endif
44 }
45 
46 inline status_t get_dependents(
47  handle_t handle,
48  handle_t * __restrict__ dependent_handles,
49  ::std::size_t * __restrict__ num_dependencies)
50 {
51 #if CUDA_VERSION >= 13000
52  static constexpr auto no_edge_data { nullptr };
53  return cuGraphNodeGetDependentNodes(handle, dependent_handles, no_edge_data, num_dependencies);
54 #else
55  return cuGraphNodeGetDependentNodes(handle, dependent_handles, num_dependencies);
56 #endif
57 }
58 
59 #if CUDA_VERSION >= 13010
60 inline template_::handle_t graph_handle_of(handle_t handle)
61 {
62  template_::handle_t graph_template_handle;
63  auto status = cuGraphNodeGetContainingGraph(handle, &graph_template_handle);
64  throw_if_error_lazy(status, "Failed obtaining the graph template containing " + graph::node::detail_::identify(handle));
65  return graph_template_handle;
66 }
67 
68 inline id_t get_id(handle_t handle)
69 {
70  id_t id;
71  auto status = cuGraphNodeGetLocalId(handle, &id);
72  throw_if_error_lazy(status, "Getting the local (DOT-printing) ID of " + identify(handle));
73  return id;
74 }
75 #endif // CUDA_VERSION >= 13010
76 
77 } // namespace detail_
78 
79 using type_t = CUgraphNodeType;
80 
81 } // namespace node
82 
96 class node_t {
97 public: // data types
98  using handle_type = node::handle_t;
99  using dependencies_type = ::std::vector<node_t>;
100  using dependents_type = ::std::vector<node_t>;
101  using type_type = node::type_t;
102  using size_type = size_t;
103 
104 // TODO: WRITEME
105 public:
106  handle_type handle() const noexcept { return handle_; }
107  template_t containing_graph() const noexcept;
108  template_::handle_t containing_graph_handle() const noexcept { return graph_template_handle_; }
109  type_type type_() const
110  {
111  type_type result;
112  auto status = cuGraphNodeGetType(handle_, &result);
113  throw_if_error_lazy(status, "Obtaining the type of " + node::detail_::identify(*this));
114  return result;
115  }
116 
117  size_t num_dependencies() const
118  {
119  size_t num_dependencies_;
120  static constexpr auto no_returned_handles = nullptr;
121  auto status = node::detail_::get_dependencies(handle_, no_returned_handles, &num_dependencies_);
122  throw_if_error_lazy(status, "Obtaining the number of nodes on which " + node::detail_::identify(*this) + " is dependent");
123  return num_dependencies_;
124  }
125 
126  size_t num_dependents() const
127  {
128  size_t num_dependents_;
129  static constexpr auto no_returned_handles = nullptr;
130  auto status = node::detail_::get_dependents(handle_, no_returned_handles, &num_dependents_);
131  throw_if_error_lazy(status, "Obtaining the number of nodes dependent on " + node::detail_::identify(*this));
132  return num_dependents_;
133  }
134 
135  dependencies_type dependencies() const
136  {
137  size_type num_dependencies_ { num_dependencies() } ;
138  ::std::vector<node::handle_t> node_handles {num_dependencies_ };
139  auto status = node::detail_::get_dependencies(handle_, node_handles.data(), &num_dependencies_);
140  throw_if_error_lazy(status, "Obtaining the set nodes on which " + node::detail_::identify(*this) + " is dependent");
141  dependencies_type result;
142  for (const auto& node_handle : node_handles) {
143  result.emplace_back(node::wrap(graph_template_handle_, node_handle));
144  }
145  return result;
146  }
147 
148  dependencies_type dependents() const
149  {
150  size_type num_dependents_ { num_dependents() } ;
151  ::std::vector<node::handle_t> node_handles {num_dependents_ };
152  auto status = node::detail_::get_dependents(handle_, node_handles.data(), &num_dependents_);
153  throw_if_error_lazy(status, "Obtaining the set nodes dependent on " + node::detail_::identify(*this));
154  dependencies_type result;
155  for (const auto& node_handle : node_handles) {
156  result.emplace_back(node::wrap(graph_template_handle_, node_handle));
157  }
158  return result;
159  }
160 
161 #if CUDA_VERSION >= 13010
162  id_t get_id() const { return node::detail_::get_id(handle_); }
165 
166  // Note: No method for the GetToolsId() API call - which is weird, and only
167  // exists for nodes, and whose use is unclear to me
168 #endif // CUDA_VERSION >= 13010
169 
170 protected: // constructors and destructors
171  node_t(template_::handle_t graph_template_handle, handle_type handle) noexcept
172  : graph_template_handle_(graph_template_handle), handle_(handle) { }
173 
174 public: // friendship
175  friend node_t node::wrap(template_::handle_t graph_handle, node::handle_t handle) noexcept;
176 
177 public: // constructors and destructors
178  node_t(const node_t&) noexcept = default; // It's a reference type, so copying is not a problem
179  node_t(node_t&&) noexcept = default; // It's a reference type, so copying is not a problem
180 
181  node_t& operator=(node_t other) noexcept
182  {
183  graph_template_handle_ = other.graph_template_handle_;
184  handle_ = other.handle_;
185  return *this;
186  }
187 
188 protected:
189  template_::handle_t graph_template_handle_;
190  handle_type handle_;
191 };
192 
193 namespace node {
194 
195 inline node_t wrap(template_::handle_t graph_handle, handle_t handle) noexcept
196 {
197  return { graph_handle, handle };
198 }
199 
200 #if CUDA_VERSION >= 13010
201 namespace detail_ {
202 
204 inline node_t from_handle(handle_t handle)
205 {
206  auto graph_template_handle = graph_handle_of(handle);
207  return wrap(graph_template_handle, handle);
208 }
209 
210 } // namespace detail_
211 #endif // CUDA_VERSION >= 13010
212 
213 } // namespace node
214 
215 } // namespace graph
216 
217 } // namespace cuda
218 
219 #endif // CUDA_VERSION >= 10000
220 
221 #endif //CUDA_API_WRAPPERS_NODE_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
::std::size_t size_t
A size type for use throughout the wrappers library (except when specific API functions limit the siz...
Definition: types.hpp:78
#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
type_t
The CUDA execution ecosystem involves different memory spaces in their relation to a GPU device or th...
Definition: pointer.hpp:41
CUresult status_t
Indicates either the result (success or error index) of a CUDA Runtime or Driver API call...
Definition: types.hpp:74