Skip to content

Commit ef24789

Browse files
committed
Inital version of sycl graph prototype
1 parent 3d2b25e commit ef24789

File tree

1 file changed

+212
-0
lines changed
  • sycl/include/sycl/ext/oneapi/experimental

1 file changed

+212
-0
lines changed
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
//==--------- graph.hpp --- SYCL graph extension ---------------------------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#pragma once
10+
11+
#include <CL/sycl/detail/defines_elementary.hpp>
12+
13+
#include <set>
14+
#include <list>
15+
16+
__SYCL_INLINE_NAMESPACE(cl) {
17+
namespace sycl {
18+
namespace ext {
19+
namespace oneapi {
20+
namespace experimental {
21+
namespace detail {
22+
23+
struct node_impl;
24+
25+
struct graph_impl;
26+
27+
using node_ptr = std::shared_ptr<node_impl>;
28+
29+
using graph_ptr = std::shared_ptr<graph_impl>;
30+
31+
class wrapper {
32+
using T = std::function<void(sycl::handler&)>;
33+
T my_func;
34+
std::vector<sycl::event> my_deps;
35+
public:
36+
wrapper(T t, const std::vector<sycl::event>& deps) : my_func(t), my_deps(deps) {};
37+
38+
void operator()(sycl::handler& cgh) {
39+
cgh.depends_on(my_deps);
40+
std::invoke(my_func,cgh);
41+
}
42+
};
43+
44+
struct node_impl {
45+
bool is_scheduled;
46+
47+
graph_ptr my_graph;
48+
sycl::event my_event;
49+
50+
std::vector<node_ptr> my_successors;
51+
std::vector<node_ptr> my_predecessors;
52+
53+
std::function<void(sycl::handler&)> my_body;
54+
55+
void exec( sycl::queue q ) {
56+
std::vector<sycl::event> __deps;
57+
for(auto i:my_predecessors) __deps.push_back(i->get_event());
58+
my_event = q.submit(wrapper{my_body,__deps});
59+
}
60+
61+
void register_successor(node_ptr n) {
62+
my_successors.push_back(n);
63+
n->register_predecessor(node_ptr(this));
64+
}
65+
66+
void register_predecessor(node_ptr n) { my_predecessors.push_back(n); }
67+
68+
sycl::event get_event(void) {return my_event;}
69+
70+
template<typename T>
71+
node_impl(graph_ptr g, T cgf) : is_scheduled(false), my_graph(g), my_body(cgf) {}
72+
73+
// Recursively adding nodes to execution stack:
74+
void topology_sort(std::list<node_ptr>& schedule) {
75+
is_scheduled = true;
76+
for(auto i:my_successors) {
77+
if(!i->is_scheduled) i->topology_sort(schedule);
78+
}
79+
schedule.push_front(node_ptr(this));
80+
}
81+
};
82+
83+
struct graph_impl {
84+
std::set<node_ptr> my_roots;
85+
std::list<node_ptr> my_schedule;
86+
87+
graph_ptr parent;
88+
89+
void exec( sycl::queue q ) {
90+
if( my_schedule.empty() ) {
91+
for(auto n : my_roots) {
92+
n->topology_sort(my_schedule);
93+
}
94+
}
95+
for(auto n : my_schedule) n->exec(q);
96+
}
97+
98+
void exec_and_wait( sycl::queue q ) {
99+
exec(q);
100+
q.wait();
101+
}
102+
103+
void add_root(node_ptr n) {
104+
my_roots.insert(n);
105+
for(auto n : my_schedule) n->is_scheduled=false;
106+
my_schedule.clear();
107+
}
108+
109+
void remove_root(node_ptr n) {
110+
my_roots.erase(n);
111+
for(auto n : my_schedule) n->is_scheduled=false;
112+
my_schedule.clear();
113+
}
114+
115+
graph_impl() {}
116+
};
117+
118+
} // namespace detail
119+
120+
class node;
121+
122+
class graph;
123+
124+
class executable_graph;
125+
126+
struct node {
127+
// TODO: add properties to distinguish between empty, host, device nodes.
128+
detail::node_ptr my_node;
129+
detail::graph_ptr my_graph;
130+
131+
template<typename T>
132+
node(detail::graph_ptr g, T cgf) : my_graph(g), my_node(new detail::node_impl(g,cgf)) {};
133+
void register_successor(node n) { my_node->register_successor(n.my_node); }
134+
void exec( sycl::queue q, sycl::event = sycl::event() ) { my_node->exec(q); }
135+
136+
void set_root() { my_graph->add_root(my_node);}
137+
138+
// TODO: Add query functions: is_root, ...
139+
};
140+
141+
class executable_graph {
142+
public:
143+
int my_tag;
144+
sycl::queue my_queue;
145+
146+
void exec_and_wait();// { my_queue.wait(); }
147+
148+
executable_graph(detail::graph_ptr g, sycl::queue q) : my_queue(q), my_tag(rand()) {
149+
g->exec(my_queue);
150+
}
151+
};
152+
153+
class graph {
154+
public:
155+
// Adding empty node with [0..n] predecessors:
156+
node add_empty_node(const std::vector<node>& dep = {});
157+
158+
// Adding node for host task
159+
template<typename T>
160+
node add_host_node(T hostTaskCallable, const std::vector<node>& dep = {});
161+
162+
// Adding device node:
163+
template<typename T>
164+
node add_device_node(T cgf, const std::vector<node>& dep = {});
165+
166+
// Adding dependency between two nodes.
167+
void make_edge(node sender, node receiver);
168+
169+
// TODO: Extend queue to directly submit graph
170+
void exec_and_wait( sycl::queue q );
171+
172+
executable_graph exec( sycl::queue q ) { return executable_graph{my_graph,q};};
173+
174+
graph() : my_graph(new detail::graph_impl()) {}
175+
176+
// Creating a subgraph (with predecessors)
177+
graph(graph& parent, const std::vector<node>& dep = {}) {}
178+
179+
bool is_subgraph();
180+
181+
private:
182+
detail::graph_ptr my_graph;
183+
};
184+
185+
void executable_graph::exec_and_wait() { my_queue.wait(); }
186+
187+
template<typename T>
188+
node graph::add_device_node(T cgf , const std::vector<node>& dep) {
189+
node _node(my_graph,cgf);
190+
if( !dep.empty() ) {
191+
for(auto n : dep) this->make_edge(n,_node);
192+
} else {
193+
_node.set_root();
194+
}
195+
return _node;
196+
}
197+
198+
void graph::make_edge(node sender, node receiver) {
199+
sender.register_successor(receiver);//register successor
200+
my_graph->remove_root(receiver.my_node); //remove receiver from root node list
201+
}
202+
203+
void graph::exec_and_wait( sycl::queue q ) {
204+
my_graph->exec_and_wait(q);
205+
};
206+
207+
} // namespace experimental
208+
} // namespace oneapi
209+
} // namespace ext
210+
} // namespace sycl
211+
} // __SYCL_INLINE_NAMESPACE(cl)
212+

0 commit comments

Comments
 (0)