11 #ifndef CUDA_API_WRAPPERS_GRAPH_TEMPLATE_HPP 12 #define CUDA_API_WRAPPERS_GRAPH_TEMPLATE_HPP 14 #if CUDA_VERSION >= 10000 45 using edge_t = ::std::pair<node_t, node_t>;
47 inline ::std::string identify(
const edge_t &edge)
49 return ::std::string(
"edge from " + node::detail_::identify(edge.first)
50 +
" to " + node::detail_::identify(edge.second));
53 template <
typename NodeOrHandle>
54 handle_t as_handle(
const NodeOrHandle& node_or_handle) noexcept
56 return node_or_handle.handle();
59 template <>
inline handle_t as_handle(
const handle_t& handle) noexcept {
return handle; }
61 template <
template <
typename>
class Container,
typename NodeOrHandle>
62 struct as_handles_partial_specialization_helper{
63 static typename ::std::conditional<
64 ::std::is_same<NodeOrHandle, handle_t>::value,
66 ::std::vector<handle_t>
68 as_handles(Container<NodeOrHandle>&& nodes_or_handles)
71 ::std::is_same<typename ::std::remove_const<NodeOrHandle>::type,
node::handle_t>::value or
72 ::std::is_same<typename ::std::remove_const<NodeOrHandle>::type,
node::handle_t>::value,
73 "Unsupported graph node dependency specifier type. Use either cuda::graph::node_t or cuda::graph::node::handle_t");
74 ::std::vector<handle_t> handles;
75 handles.reserve(nodes_or_handles.size());
77 nodes_or_handles.begin(),
78 nodes_or_handles.end(),
79 ::std::back_inserter(handles),
80 as_handle<NodeOrHandle> );
85 template <
template <
typename>
class Container>
86 struct as_handles_partial_specialization_helper<Container,
handle_t> {
87 Container<handle_t> as_handles(Container<handle_t>&& node_handles)
93 template <
template <
typename>
class Container,
typename NodeOrHandle>
94 static typename ::std::conditional<
95 ::std::is_same<NodeOrHandle, handle_t>::value,
97 ::std::vector<handle_t>
99 as_handles(Container<NodeOrHandle>&& nodes_or_handles)
101 return as_handles_partial_specialization_helper<Container, handle_t>::as_handles(
102 ::std::forward<Container<NodeOrHandle>>(nodes_or_handles));
109 namespace template_ {
111 template_t
wrap(
handle_t handle,
bool take_ownership =
false) noexcept;
115 ::std::string identify(
const template_t& template_);
117 #if CUDA_VERSION >= 13010 121 auto status = cuGraphGetId(handle, &
id);
125 #endif // CUDA_VERSION >= 13010 127 inline CUresult delete_edges(
133 #if CUDA_VERSION >= 13000 134 static constexpr
const auto no_edge_data =
nullptr;
135 return cuGraphRemoveDependencies(template_handle, source_handles, destination_handles, no_edge_data, num_edges);
137 return cuGraphRemoveDependencies(template_handle, source_handles, destination_handles, num_edges);
143 span<const node::handle_t> edge_source_handles,
144 span<const node::handle_t> edge_destination_handles)
146 auto num_edges = edge_source_handles.size();
147 assert(edge_source_handles.size() == num_edges &&
"Mismatched sizes of sources and destinations");
149 template_handle,edge_source_handles.data(), edge_destination_handles.data(), num_edges);
154 span<const node_t> edge_sources,
155 span<const node_t> edge_destinations)
157 auto num_edges = edge_sources.size();
158 assert(edge_destinations.size() == num_edges &&
"Mismatched sizes of sources and destinations");
161 auto handles_buffer = ::std::vector<node::handle_t>{num_edges * 2};
163 auto handles_iter = handles_buffer;
164 ::std::transform(edge_sources.begin(), edge_sources.end(), handles_buffer.data(),
165 [](
const node_t &node) {
return node.handle(); });
166 ::std::transform(edge_destinations.begin(), edge_destinations.end(), handles_buffer.data() + num_edges,
167 [](
const node_t &node) {
return node.handle(); });
169 span<const node::handle_t> edge_source_handles { handles_buffer.data(), num_edges };
170 span<const node::handle_t> edge_destination_handles { handles_buffer.data() + num_edges, num_edges };
171 return delete_edges(template_handle, edge_source_handles, edge_destination_handles);
180 #if CUDA_VERSION >= 13000 181 static constexpr
const auto no_edge_data =
nullptr;
182 return cuGraphAddDependencies(template_handle, source_handles, destination_handles, no_edge_data, num_edges);
184 return cuGraphAddDependencies(template_handle, source_handles, destination_handles, num_edges);
191 span<const node_t> edge_sources,
192 span<const node_t> edge_destinations)
194 auto num_edges = edge_sources.size();
195 assert(edge_destinations.size() == num_edges &&
"Mismatched sizes of sources and destinations");
198 auto handles_buffer = ::std::vector<node::handle_t>{num_edges * 2};
200 auto handles_iter = handles_buffer;
201 ::std::transform(edge_sources.begin(), edge_sources.end(), handles_buffer.data(),
202 [](
const node_t &node) {
return node.handle(); });
203 ::std::transform(edge_destinations.begin(), edge_destinations.end(), handles_buffer.data() + num_edges,
204 [](
const node_t &node) {
return node.handle(); });
207 const node::handle_t* destinations_handles = handles_buffer.data() + num_edges;
208 auto result = insert_edges(
209 template_handle,sources_handles, destinations_handles, edge_sources.size());
215 span<const node::detail_::edge_t> edges)
218 auto handles_buffer = ::std::vector<node::handle_t>{edges.size() * 2};
219 auto sources_iterator = handles_buffer.begin();
220 auto destinations_iterator = handles_buffer.begin() + edges.size();
221 for(
const auto& edge : edges) {
222 *(sources_iterator++) = edge.first.handle();
223 *(destinations_iterator++) = edge.second.handle();
226 const node::handle_t* destinations_handles = handles_buffer.data() + edges.size();
227 auto result = delete_edges(
228 template_handle,sources_handles, destinations_handles, edges.size());
235 span<const node::detail_::edge_t> edges)
238 auto handles_buffer = ::std::vector<node::handle_t>{edges.size() * 2};
239 auto sources_iterator = handles_buffer.begin();
240 auto destinations_iterator = handles_buffer.begin() + edges.size();
241 for(
const auto& edge : edges) {
242 *(sources_iterator++) = edge.first.handle();
243 *(destinations_iterator++) = edge.second.handle();
246 const node::handle_t* destinations_handles = handles_buffer.data() + edges.size();
247 auto result = insert_edges(
248 template_handle,sources_handles, destinations_handles, edges.size());
252 template <node::kind_t Kind>
253 status_t invoke_inserter_possibly_with_context(
254 cuda::detail_::bool_constant<false>,
257 CUgraphNode* dependency_handles,
258 size_t num_dependency_handles,
259 typename node::detail_::kind_traits<Kind>::raw_parameters_type&
263 auto raw_params_maybe_ptr = node::detail_::maybe_add_ptr<Kind>(raw_params);
264 return node::detail_::kind_traits<Kind>::inserter(
266 graph_template_handle,
268 num_dependency_handles,
269 raw_params_maybe_ptr);
272 template <node::kind_t Kind>
273 status_t invoke_inserter_possibly_with_context(
274 cuda::detail_::bool_constant<true>,
277 CUgraphNode* dependency_handles,
278 size_t num_dependency_handles,
279 typename node::detail_::kind_traits<Kind>::raw_parameters_type&
283 auto raw_params_maybe_ptr = node::detail_::maybe_add_ptr<Kind>(raw_params);
284 return node::detail_::kind_traits<Kind>::inserter(
286 graph_template_handle,
288 num_dependency_handles,
289 raw_params_maybe_ptr,
293 template <node::kind_t Kind>
297 typename node::detail_::kind_traits<Kind>::raw_parameters_type raw_params)
299 using traits_type =
typename node::detail_::kind_traits<Kind>;
302 const bool context_needed_but_missing =
303 traits_type::inserter_takes_context and context_handle == context::detail_::none;
304 if (context_needed_but_missing) {
305 throw ::std::invalid_argument(
306 "Attempt to insert a CUDA graph template " + ::std::string(traits_type::name)
307 +
" node without specifying an execution context");
311 auto no_dependency_handles =
nullptr;
312 size_t no_dependencies_size = 0;
313 auto status = invoke_inserter_possibly_with_context<Kind>(
314 cuda::detail_::bool_constant<traits_type::inserter_takes_context>{},
316 graph_template_handle,
317 no_dependency_handles,
318 no_dependencies_size,
321 throw_if_error_lazy(status,
"Inserting a " + ::std::string(traits_type::name) +
" node into " 322 + template_::detail_::identify(graph_template_handle));
323 return new_node_handle;
326 template <node::kind_t Kind,
typename... Ts>
327 node::typed_node_t<Kind> build_params_and_insert_node(
330 Ts&&... params_ctor_args)
333 using traits_type =
typename node::detail_::kind_traits<Kind>;
334 using parameters_t =
typename traits_type::parameters_type;
340 parameters_t params { ::std::forward<Ts>(params_ctor_args)... };
341 typename traits_type::raw_parameters_type raw_params = traits_type::marshal(params);
342 auto node_handle = insert_node<Kind>(graph_template_handle, context_handle, raw_params);
343 return node::wrap<Kind>(graph_template_handle, node_handle, ::std::move(params));
346 template <node::kind_t Kind,
typename... Ts>
347 node::typed_node_t<Kind> get_context_handle_build_params_and_insert_node(
348 cuda::detail_::true_type,
350 const context_t& context,
351 Ts&&... params_ctor_args)
353 return build_params_and_insert_node<Kind>(graph_template_handle, context.handle(), ::std::forward<Ts>(params_ctor_args)...);
356 template <node::kind_t Kind,
typename... Ts>
357 node::typed_node_t<Kind> get_context_handle_build_params_and_insert_node(
358 cuda::detail_::false_type,
360 Ts&&... params_ctor_args)
362 auto current_context_handle = context::current::detail_::get_handle();
364 return build_params_and_insert_node<Kind>(
365 graph_template_handle, current_context_handle, ::std::forward<Ts>(params_ctor_args)...);
369 template <node::kind_t Kind,
typename... Ts>
370 node::typed_node_t<Kind> build_params_and_insert_node_wrapper(
371 cuda::detail_::false_type ,
373 Ts&&... params_ctor_args)
375 return build_params_and_insert_node<Kind>(graph_template_handle, context::detail_::none, ::std::forward<Ts>(params_ctor_args)...);
378 template <node::kind_t Kind,
typename T,
typename... Ts>
379 node::typed_node_t<Kind> build_params_and_insert_node_wrapper(
380 cuda::detail_::true_type,
383 Ts&&... params_ctor_args)
385 static constexpr
const bool first_arg_is_a_context =
386 ::std::is_same<typename cuda::detail_::remove_reference_t<T>,
cuda::context_t>::value;
387 return get_context_handle_build_params_and_insert_node<Kind>(
389 cuda::detail_::bool_constant<first_arg_is_a_context>{},
390 graph_template_handle, ::std::forward<T>(first_arg), ::std::forward<Ts>(params_ctor_args)...);
399 #if CUDA_VERSION >= 13000 400 static constexpr
auto no_edge_data {
nullptr };
401 return cuGraphGetEdges(template_handle, source_handles, destination_handles, no_edge_data, num_nodes);
403 return cuGraphGetEdges(template_handle, source_handles, destination_handles, num_nodes);
423 using node_ref_type = node_t;
427 using edge_type = ::std::pair<node_ref_type, node_ref_type>;
429 using node_ref_container_type = ::std::vector<node_t>;
433 using edge_container_type = ::std::vector<edge_type>;
438 handle_type handle() const noexcept {
return handle_; }
441 bool is_owning() const noexcept {
return owning_; }
445 #if CUDA_VERSION >= 11030 446 struct dot_printing_options_t {
448 bool use_runtime_types;
465 } external_semaphore;
467 bool kernel_node_attributes;
468 bool node_and_kernel_function_handles;
470 unsigned compose()
const {
472 | (debug_data ? CU_GRAPH_DEBUG_DOT_FLAGS_VERBOSE : 0)
473 | (use_runtime_types ? CU_GRAPH_DEBUG_DOT_FLAGS_RUNTIME_TYPES : 0)
474 | (node_params.launch.kernel ? CU_GRAPH_DEBUG_DOT_FLAGS_KERNEL_NODE_PARAMS : 0)
475 | (node_params.launch.host_function ? CU_GRAPH_DEBUG_DOT_FLAGS_HOST_NODE_PARAMS : 0)
476 #if CUDA_VERSION >= 11040 477 | (node_params.memory_ops.allocate ? CU_GRAPH_DEBUG_DOT_FLAGS_MEM_ALLOC_NODE_PARAMS : 0)
478 | (node_params.memory_ops.free ? CU_GRAPH_DEBUG_DOT_FLAGS_MEM_FREE_NODE_PARAMS : 0)
479 #endif // CUDA_VERSION >= 11040 480 | (node_params.memory_ops.copy ? CU_GRAPH_DEBUG_DOT_FLAGS_MEMCPY_NODE_PARAMS : 0)
481 | (node_params.memory_ops.set ? CU_GRAPH_DEBUG_DOT_FLAGS_MEMSET_NODE_PARAMS : 0)
482 | (node_params.event ? CU_GRAPH_DEBUG_DOT_FLAGS_EVENT_NODE_PARAMS : 0)
483 | (node_params.external_semaphore.signal ? CU_GRAPH_DEBUG_DOT_FLAGS_EXT_SEMAS_SIGNAL_NODE_PARAMS : 0)
484 | (node_params.external_semaphore.wait ? CU_GRAPH_DEBUG_DOT_FLAGS_EXT_SEMAS_WAIT_NODE_PARAMS : 0)
485 | (kernel_node_attributes ? CU_GRAPH_DEBUG_DOT_FLAGS_KERNEL_NODE_ATTRIBUTES : 0)
486 | (node_and_kernel_function_handles ? CU_GRAPH_DEBUG_DOT_FLAGS_HANDLES : 0)
491 #endif // CUDA_VERSION >= 11030 500 template_t clone()
const 502 handle_type clone_handle;
503 auto status = cuGraphClone(&clone_handle, handle_);
505 return template_t{ clone_handle, do_take_ownership };
508 #if CUDA_VERSION >= 11030 517 void print_dot(
const char* dot_filename, dot_printing_options_t printing_options = {})
const 519 auto status = cuGraphDebugDotPrint(handle_, dot_filename, printing_options.compose());
520 throw_if_error_lazy(status,
"Printing " + template_::detail_::identify(*
this) +
" to file " + dot_filename);
522 #endif // CUDA_VERSION >= 11030 526 size_type num_nodes()
const 529 auto status = cuGraphGetNodes(handle_,
nullptr, &num_nodes_);
530 throw_if_error_lazy(status,
"Obtaining the number of nodes in " + template_::detail_::identify(*
this));
541 node_ref_container_type nodes()
const 543 size_type num_nodes_ { num_nodes() } ;
544 ::std::vector<node::handle_t> node_handles { num_nodes_ };
545 auto status = cuGraphGetNodes(handle_, node_handles.data(), &num_nodes_);
546 throw_if_error_lazy(status,
"Obtaining the set of nodes of " + template_::detail_::identify(*
this));
547 node_ref_container_type node_refs;
548 for (
const auto& node_handle : node_handles) {
549 node_refs.emplace_back(
node::wrap(handle_, node_handle));
558 size_type num_roots()
const 562 auto status = cuGraphGetRootNodes(handle_,
nullptr, &num_roots_);
563 throw_if_error_lazy(status,
"Obtaining the number of root nodes in " + template_::detail_::identify(*
this));
571 node_ref_container_type roots()
const 574 size_type num_roots_ {num_roots() } ;
575 ::std::vector<node::handle_t> root_node_handles {num_roots_ };
576 auto status = cuGraphGetRootNodes(handle_, root_node_handles.data(), &num_roots_);
577 throw_if_error_lazy(status,
"Obtaining the set of root nodes of " + template_::detail_::identify(*
this));
578 node_ref_container_type root_node_refs;
579 for (
const auto& node_handle : root_node_handles) {
580 root_node_refs.emplace_back(
node::wrap(handle_, node_handle));
582 return root_node_refs;
586 size_type num_edges()
const 589 auto status = template_::detail_::get_edges(handle_,
nullptr,
nullptr, &num_edges);
590 throw_if_error_lazy(status,
"Obtaining the number of edges in " + template_::detail_::identify(*
this));
594 edge_container_type edges()
const 596 size_type num_edges_ { num_edges() } ;
597 ::std::vector<node::handle_t> from_node_handles { num_edges_ };
598 ::std::vector<node::handle_t> to_node_handles { num_edges_ };
599 auto status = template_::detail_::get_edges(
600 handle_, from_node_handles.data(), to_node_handles.data(), &num_edges_);
601 throw_if_error_lazy(status,
"Obtaining the set of edges in " + template_::detail_::identify(*
this));
602 edge_container_type edges;
605 auto from_iter = from_node_handles.cbegin();
606 auto to_iter = from_node_handles.cbegin();
607 for (; from_iter != from_node_handles.cend(); from_iter++, to_iter++) {
608 assert(to_iter != to_node_handles.cend());
609 auto from_node_ref =
node::wrap(handle_, *from_iter);
610 auto to_node_ref =
node::wrap(handle_, *to_iter);
611 edges.emplace_back(from_node_ref, to_node_ref);
629 const template_t& associated_template;
634 insert_t(
const template_t& template_) : associated_template(template_) {}
636 void edge(node_ref_type source, node_ref_type dest)
const 641 } handles { source.handle(), dest.handle() };
642 static constexpr
const size_t remove_just_one = 1;
643 auto status = template_::detail_::insert_edges(
644 handle(), &handles.source, &handles.dest, remove_just_one);
645 throw_if_error_lazy(status,
"Inserting " + node::detail_::identify(edge_type{source, dest})
646 +
" into " + template_::detail_::identify(associated_template));
649 void edge(edge_type edge_)
const 651 return edge(edge_.first, edge_.second);
654 void edges(span<const node_ref_type> sources, span<const node_ref_type> destinations)
const 656 if (sources.size() != destinations.size()) {
657 throw ::std::invalid_argument(
658 "Differing number of source nodes and destination nodes (" 659 + ::std::to_string(sources.size()) +
" != " + ::std::to_string(destinations.size())
660 +
" in a request to insert edges into " + template_::detail_::identify(associated_template) );
662 auto status = template_::detail_::insert_edges(handle(), sources, destinations);
664 throw_if_error_lazy(status,
"Destroying " + ::std::to_string(sources.size()) +
" edges in " 665 + template_::detail_::identify(associated_template));
668 void edges(span<const edge_type> edges)
const 670 auto status = template_::detail_::insert_edges(handle(), edges);
673 + template_::detail_::identify(associated_template));
676 template <node::kind_t Kind,
typename T,
typename... Ts>
677 typename node::typed_node_t<Kind> node(
678 T&& arg, Ts&&... node_params_ctor_arguments)
const 683 static constexpr
const bool inserter_takes_context = node::detail_::kind_traits<Kind>::inserter_takes_context;
684 return template_::detail_::build_params_and_insert_node_wrapper<Kind>(
685 cuda::detail_::bool_constant<inserter_takes_context>{}, handle(),
686 ::std::forward<T>(arg), ::std::forward<Ts>(node_params_ctor_arguments)...);
698 const template_t &associated_template;
699 handle_type handle() const noexcept {
return associated_template.handle(); }
702 delete_t(
const template_t &template_) : associated_template(template_) {}
704 void node(node_ref_type node)
const 706 auto status = cuGraphDestroyNode(node.handle());
708 +
" in " + template_::detail_::identify(associated_template));
711 void edge(edge_type
const& edge_)
const 717 } handles { edge_.first.handle(), edge_.second.handle() };
718 static constexpr
size_t remove_single_edge { 1 };
719 auto status = template_::detail_::delete_edges(
720 handle(), &handles.source, &handles.dest, remove_single_edge);
723 +
" in " + template_::detail_::identify(associated_template));
726 void edges(span<const node_ref_type> sources, span<const node_ref_type> destinations)
const 728 if (sources.size() != destinations.size()) {
729 throw ::std::invalid_argument(
730 "Differing number of source nodes and destination nodes (" 731 + ::std::to_string(sources.size()) +
" != " + ::std::to_string(destinations.size())
732 +
" in a request to insert edges into " + template_::detail_::identify(associated_template) );
734 auto status = template_::detail_::delete_edges(handle(), sources, destinations);
736 throw_if_error_lazy(status,
"Destroying " + ::std::to_string(sources.size()) +
" edges in " 737 + template_::detail_::identify(associated_template));
740 void edges(span<edge_type> edges)
const 742 auto status = template_::detail_::delete_edges(handle(), edges);
745 + template_::detail_::identify(associated_template));
751 friend template_t
template_::wrap(handle_type handle,
bool take_ownership) noexcept;
754 template_t(handle_type handle,
bool owning) noexcept
755 : handle_(handle), owning_(owning)
759 template_t(
const template_t& other) noexcept =
delete;
760 template_t(template_t&& other) noexcept : template_t(other.handle_, other.owning_)
762 other.owning_ =
false;
765 ~template_t() DESTRUCTOR_EXCEPTION_SPEC
768 auto status = cuGraphDestroy(handle_);
769 #ifdef THROW_IN_DESTRUCTORS 778 template_t& operator=(
const template_t&) =
delete;
779 template_t& operator=(template_t&& other) noexcept
781 ::std::swap(handle_, other.handle_);
782 ::std::swap(owning_, other.owning_);
787 instance_t instantiate(
788 #
if CUDA_VERSION >= 11040
789 bool free_previous_allocations_before_relaunch =
false 791 #
if CUDA_VERSION >= 11700
792 ,
bool use_per_node_priorities =
false 794 #
if CUDA_VERSION >= 12000
795 ,
bool upload_on_instantiation =
false 796 ,
bool make_device_launchable =
false 800 #if CUDA_VERSION >= 13010 805 return template_::detail_::get_id(handle_);
807 #endif // CUDA_VERSION >= 13010 810 const insert_t insert { *
this };
811 const delete_t delete_ { *
this };
818 namespace template_ {
820 inline template_t
wrap(
handle_t handle,
bool take_ownership) noexcept
822 return { handle, take_ownership };
825 inline template_t create()
827 constexpr
const unsigned flags { 0 };
829 auto status = cuGraphCreate(&handle, flags);
831 return wrap(handle, do_take_ownership);
834 inline ::std::string identify(
const template_t& template_)
836 return "CUDA execution graph template at " + cuda::detail_::ptr_as_hex(template_.handle());
839 constexpr const ::std::initializer_list<node_t> no_dependencies {};
841 template <node::kind_t Kind,
template <
typename>
class Container,
typename NodeOrHandle,
typename... NodeParametersCtorParams>
842 node::typed_node_t<Kind> insert_node(
843 const template_t& graph,
844 Container<NodeOrHandle> dependencies,
845 NodeParametersCtorParams... node_parameters_ctor_params)
847 using traits_type =
typename node::detail_::kind_traits<Kind>;
848 node::parameters_t<Kind> params { ::std::forward<NodeParametersCtorParams>(node_parameters_ctor_params)... };
849 auto raw_params = traits_type::marshal(params);
850 auto untyped_node = template_::detail_::insert_node(graph.handle(), raw_params, dependencies);
851 return node::wrap<Kind>(untyped_node.containing_graph(), untyped_node.handle(), params);
858 inline template_t create()
860 return template_::create();
878 inline optional<node_t> find_in_clone(node_t node,
const template_t& cloned_graph)
883 auto status = cuGraphNodeFindInClone(&search_result, node.handle(), cloned_graph.handle());
884 if (status == cuda::status::invalid_value and search_result !=
nullptr) {
887 throw_if_error_lazy(status,
"Searching for a copy of " + node::detail_::identify(node) +
" in " + template_::detail_::identify(cloned_graph));
888 return node::wrap(cloned_graph.handle(), search_result);
895 #endif // CUDA_VERSION >= 10000 897 #endif // CUDA_API_WRAPPERS_GRAPH_TEMPLATE_HPP Wrapper class for a CUDA context.
Definition: context.hpp:249
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 wait(const event_t &event)
Have the calling thread wait - either busy-waiting or blocking - and return only after this event has...
Definition: event.hpp:457
void free(void *ptr)
Free a region of device-side memory (regardless of how it was allocated)
Definition: memory.hpp:126
void launch(Kernel &&kernel, launch_configuration_t launch_configuration, KernelParameters &&... parameters)
Variant of enqueue_launch for use with the default stream in the current context. ...
Definition: kernel_launch.hpp:396
::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'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
Facilities for exception-based handling of Runtime and Driver API errors, including a basic exception...
Graph template node proxy (base-)class base-class node_t and supporting code.
Fundamental CUDA-related type definitions.
CUresult status_t
Indicates either the result (success or error index) of a CUDA Runtime or Driver API call...
Definition: types.hpp:74