Kokkos Core Kernels Package Version of the Day
Loading...
Searching...
No Matches
Kokkos_Graph.hpp
1//@HEADER
2// ************************************************************************
3//
4// Kokkos v. 4.0
5// Copyright (2022) National Technology & Engineering
6// Solutions of Sandia, LLC (NTESS).
7//
8// Under the terms of Contract DE-NA0003525 with NTESS,
9// the U.S. Government retains certain rights in this software.
10//
11// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
12// See https://kokkos.org/LICENSE for license information.
13// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14//
15//@HEADER
16
17#ifndef KOKKOS_GRAPH_HPP
18#define KOKKOS_GRAPH_HPP
19#ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
20#define KOKKOS_IMPL_PUBLIC_INCLUDE
21#define KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_GRAPH
22#endif
23
24#include <Kokkos_Macros.hpp>
25#include <impl/Kokkos_Error.hpp> // KOKKOS_EXPECTS
26
27#include <Kokkos_Graph_fwd.hpp>
28#include <impl/Kokkos_GraphImpl_fwd.hpp>
29
30// GraphAccess needs to be defined, not just declared
31#include <impl/Kokkos_GraphImpl.hpp>
32
33#include <functional>
34#include <memory>
35
36namespace Kokkos {
37namespace Experimental {
38
39//==============================================================================
40// <editor-fold desc="Graph"> {{{1
41
42template <class ExecutionSpace = DefaultExecutionSpace>
43struct [[nodiscard]] Graph {
45
46 public:
47 //----------------------------------------------------------------------------
48 // <editor-fold desc="public member types"> {{{2
49
50 using execution_space = ExecutionSpace;
51 using graph = Graph;
52 using root_t = GraphNodeRef<ExecutionSpace>;
53
54 // </editor-fold> end public member types }}}2
55 //----------------------------------------------------------------------------
56
57 private:
58 //----------------------------------------------------------------------------
59 // <editor-fold desc="friends"> {{{2
60
61 friend struct Kokkos::Impl::GraphAccess;
62
63 // </editor-fold> end friends }}}2
64 //----------------------------------------------------------------------------
65
66 //----------------------------------------------------------------------------
67 // <editor-fold desc="private data members"> {{{2
68
69 using impl_t = Kokkos::Impl::GraphImpl<ExecutionSpace>;
70 using root_impl_t = typename impl_t::root_node_impl_t;
71
72 std::shared_ptr<impl_t> m_impl_ptr = nullptr;
73 std::shared_ptr<root_impl_t> m_root = nullptr;
74
75 // </editor-fold> end private data members }}}2
76 //----------------------------------------------------------------------------
77
78 public:
79 // Construct an empty graph with a root node.
80 Graph(ExecutionSpace exec = ExecutionSpace{})
81 : m_impl_ptr{std::make_shared<impl_t>(std::move(exec))},
82 m_root{m_impl_ptr->create_root_node_ptr()} {}
83
84#if defined(KOKKOS_ENABLE_CUDA) || defined(KOKKOS_ENABLE_HIP) || \
85 defined(KOKKOS_ENABLE_SYCL)
86 // Construct a graph from a native graph, add a root node.
87 template <typename T>
88#if defined(KOKKOS_ENABLE_CXX20)
89 requires std::same_as<ExecutionSpace, Kokkos::DefaultExecutionSpace>
90#endif
91 Graph(ExecutionSpace exec, T&& native_graph)
92 : m_impl_ptr{std::make_shared<impl_t>(std::move(exec),
93 std::forward<T>(native_graph))},
94 m_root{m_impl_ptr->create_root_node_ptr()} {
95 }
96#endif
97
98 ExecutionSpace const& get_execution_space() const {
99 return m_impl_ptr->get_execution_space();
100 }
101
102 // Once the graph is instantiated, it is undefined behavior to add nodes.
103 // TODO Add a locking mechanism to avoid users shooting themselves
104 // in the foot.
105 void instantiate() {
106 KOKKOS_EXPECTS(bool(m_impl_ptr))
107 (*m_impl_ptr).instantiate();
108 }
109
110 auto root_node() const { return root_t{m_impl_ptr, m_root}; }
111
112 void submit(const execution_space& exec) const {
113 KOKKOS_EXPECTS(bool(m_impl_ptr))
114 (*m_impl_ptr).submit(exec);
115 }
116
117 void submit() const { submit(get_execution_space()); }
118
119 decltype(auto) native_graph();
120
121 decltype(auto) native_graph_exec();
122};
123
124// </editor-fold> end Graph }}}1
125//==============================================================================
126
127//==============================================================================
128// <editor-fold desc="when_all"> {{{1
129
130template <class... PredecessorRefs>
131// constraints (not intended for subsumption, though...)
132// ((remove_cvref_t<PredecessorRefs> is a specialization of
133// GraphNodeRef with get_root().get_graph_impl() as its GraphImpl)
134// && ...)
135auto when_all(PredecessorRefs&&... arg_pred_refs) {
136 // TODO @graph @desul-integration check the constraints and preconditions
137 // once we have folded conjunctions from
138 // desul
139 static_assert(sizeof...(PredecessorRefs) > 0,
140 "when_all() needs at least one predecessor.");
141 auto graph_ptr_impl =
142 Kokkos::Impl::GraphAccess::get_graph_weak_ptr(
143 std::get<0>(std::forward_as_tuple(arg_pred_refs...)))
144 .lock();
145 auto node_ptr_impl = graph_ptr_impl->create_aggregate_ptr(arg_pred_refs...);
146 graph_ptr_impl->add_node(node_ptr_impl);
147 (graph_ptr_impl->add_predecessor(node_ptr_impl, arg_pred_refs), ...);
148 return Kokkos::Impl::GraphAccess::make_graph_node_ref(
149 std::move(graph_ptr_impl), std::move(node_ptr_impl));
150}
151
152// </editor-fold> end when_all }}}1
153//==============================================================================
154
155//==============================================================================
156// <editor-fold desc="create_graph"> {{{1
157
158template <class ExecutionSpace, class Closure>
159Graph<ExecutionSpace> create_graph(ExecutionSpace ex, Closure&& arg_closure) {
160 // Create a shared pointer to the graph:
161 // We need an attorney class here so we have an implementation friend to
162 // create a Graph class without graph having public constructors. We can't
163 // just make `create_graph` itself a friend because of the way that friend
164 // function template injection works.
165 Graph<ExecutionSpace> rv{std::move(ex)};
166 // Invoke the user's graph construction closure
167 ((Closure&&)arg_closure)(rv.root_node());
168 // and given them back the graph
169 // KOKKOS_ENSURES(rv.m_impl_ptr.use_count() == 1)
170 return rv;
171}
172
173template <
174 class ExecutionSpace = DefaultExecutionSpace,
175 class Closure = Kokkos::Impl::DoNotExplicitlySpecifyThisTemplateParameter>
176std::enable_if_t<
178 Graph<ExecutionSpace>>
179create_graph(Closure&& arg_closure) {
180 return create_graph(ExecutionSpace{}, (Closure&&)arg_closure);
181}
182
183// </editor-fold> end create_graph }}}1
184//==============================================================================
185
186template <class ExecutionSpace>
187decltype(auto) Graph<ExecutionSpace>::native_graph() {
188 KOKKOS_EXPECTS(bool(m_impl_ptr));
189#if defined(KOKKOS_ENABLE_CUDA)
190 if constexpr (std::is_same_v<ExecutionSpace, Kokkos::Cuda>) {
191 return m_impl_ptr->cuda_graph();
192 }
193#elif defined(KOKKOS_ENABLE_HIP) && defined(KOKKOS_IMPL_HIP_NATIVE_GRAPH)
194 if constexpr (std::is_same_v<ExecutionSpace, Kokkos::HIP>) {
195 return m_impl_ptr->hip_graph();
196 }
197#elif defined(KOKKOS_ENABLE_SYCL) && defined(KOKKOS_IMPL_SYCL_GRAPH_SUPPORT)
198 if constexpr (std::is_same_v<ExecutionSpace, Kokkos::SYCL>) {
199 return m_impl_ptr->sycl_graph();
200 }
201#endif
202}
203
204template <class ExecutionSpace>
205decltype(auto) Graph<ExecutionSpace>::native_graph_exec() {
206 KOKKOS_EXPECTS(bool(m_impl_ptr));
207#if defined(KOKKOS_ENABLE_CUDA)
208 if constexpr (std::is_same_v<ExecutionSpace, Kokkos::Cuda>) {
209 return m_impl_ptr->cuda_graph_exec();
210 }
211#elif defined(KOKKOS_ENABLE_HIP) && defined(KOKKOS_IMPL_HIP_NATIVE_GRAPH)
212 if constexpr (std::is_same_v<ExecutionSpace, Kokkos::HIP>) {
213 return m_impl_ptr->hip_graph_exec();
214 }
215#elif defined(KOKKOS_ENABLE_SYCL) && defined(KOKKOS_IMPL_SYCL_GRAPH_SUPPORT)
216 if constexpr (std::is_same_v<ExecutionSpace, Kokkos::SYCL>) {
217 return m_impl_ptr->sycl_graph_exec();
218 }
219#endif
220}
221
222} // end namespace Experimental
223} // namespace Kokkos
224
225// Even though these things are separable, include them here for now so that
226// the user only needs to include Kokkos_Graph.hpp to get the whole facility.
227#include <Kokkos_GraphNode.hpp>
228
229#include <impl/Kokkos_GraphNodeImpl.hpp>
230#include <impl/Kokkos_GraphNodeThenImpl.hpp>
231#include <impl/Kokkos_Default_Graph_Impl.hpp>
232#include <Cuda/Kokkos_Cuda_Graph_Impl.hpp>
233#if defined(KOKKOS_ENABLE_HIP)
234// The implementation of hipGraph in ROCm 5.2 is bugged, so we cannot use it.
235#if defined(KOKKOS_IMPL_HIP_NATIVE_GRAPH)
236#include <HIP/Kokkos_HIP_Graph_Impl.hpp>
237#endif
238#endif
239#ifdef KOKKOS_IMPL_SYCL_GRAPH_SUPPORT
240#include <SYCL/Kokkos_SYCL_Graph_Impl.hpp>
241#endif
242#ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_GRAPH
243#undef KOKKOS_IMPL_PUBLIC_INCLUDE
244#undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_GRAPH
245#endif
246#endif // KOKKOS_GRAPH_HPP
A thread safe view to a bitset.