Skip to content

Commit 805a518

Browse files
authored
[SYCL][Graph] command_graph queue constructor (#12330)
Feedback from Jack Kirk (@JackAKirk) that SYCL classes with a sycl::context and sycl::device constructor normally have a matching constructor taking a sycl::queue which replaces the context and device. Being able to use a queue constructor makes it easier to port code from CUDA/HIP where there is not a concept analogous to SYCL contexts. Our tests/examples also commonly use the pattern ```cpp queue Queue; command_graph Graph {Queue.get_context(), Queue.get_device()} ``` So being able to use a queue constructor is also a more concise way to call the constructor in a lot of cases, regardless of platform.
1 parent 16f76ea commit 805a518

File tree

11 files changed

+225
-2
lines changed

11 files changed

+225
-2
lines changed

sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ Erik Tomusk, Codeplay +
5353
Bjoern Knafla, Codeplay +
5454
Lukas Sommer, Codeplay +
5555
Maxime France-Pillois, Codeplay +
56+
Jack Kirk, Codeplay +
5657
Ronan Keryell, AMD +
5758
Andrey Alekseenko, KTH Royal Institute of Technology +
5859

@@ -372,6 +373,9 @@ public:
372373
command_graph(const context& syclContext, const device& syclDevice,
373374
const property_list& propList = {});
374375
376+
command_graph(const queue& syclQueue,
377+
const property_list& propList = {});
378+
375379
command_graph<graph_state::executable>
376380
finalize(const property_list& propList = {}) const;
377381
@@ -611,8 +615,34 @@ associated with `syclContext`.
611615
* Throws synchronously with error code `invalid` if `syclDevice`
612616
<<device-info-query, reports this extension as unsupported>>.
613617

614-
* Throws synchronously with error code `invalid` if the backend associated
615-
with `syclDevice` is not supported.
618+
|
619+
[source,c++]
620+
----
621+
command_graph(const queue& syclQueue,
622+
const property_list& propList = {});
623+
----
624+
|Simplified constructor form where `syclQueue` provides the device and context.
625+
Zero or more properties can be provided to the constructed SYCL `command_graph`
626+
via an instance of `property_list`.
627+
628+
Preconditions:
629+
630+
* This constructor is only available when the `command_graph` state is
631+
`graph_state::modifiable`.
632+
633+
Parameters:
634+
635+
* `syclQueue` - Queue which provides the SYCL device and context for the graph,
636+
which are immutable characteristics of the graph. All other properties of the
637+
queue are ignored for the purposes of graph creation.
638+
639+
* `propList` - Optional parameter for passing properties. Valid `command_graph`
640+
constructor properties are listed in Section <<graph-properties, Graph Properties>>.
641+
642+
Exceptions:
643+
644+
* Throws synchronously with error code `invalid` if the device associated with
645+
`syclQueue` <<device-info-query, reports this extension as unsupported>>.
616646

617647
|===
618648

sycl/include/sycl/ext/oneapi/experimental/graph.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,12 @@ class __SYCL_EXPORT modifiable_command_graph {
161161
modifiable_command_graph(const context &SyclContext, const device &SyclDevice,
162162
const property_list &PropList = {});
163163

164+
/// Constructor.
165+
/// @param SyclQueue Queue to use for the graph device and context.
166+
/// @param PropList Optional list of properties to pass.
167+
modifiable_command_graph(const queue &SyclQueue,
168+
const property_list &PropList = {});
169+
164170
/// Add an empty node to the graph.
165171
/// @param PropList Property list used to pass [0..n] predecessor nodes.
166172
/// @return Constructed empty node which has been added to the graph.
@@ -325,6 +331,12 @@ class command_graph : public detail::modifiable_command_graph {
325331
const property_list &PropList = {})
326332
: modifiable_command_graph(SyclContext, SyclDevice, PropList) {}
327333

334+
/// Constructor.
335+
/// @param SyclQueue Queue to use for the graph device and context.
336+
/// @param PropList Optional list of properties to pass.
337+
command_graph(const queue &SyclQueue, const property_list &PropList = {})
338+
: modifiable_command_graph(SyclQueue, PropList) {}
339+
328340
private:
329341
/// Constructor used internally by the runtime.
330342
/// @param Impl Detail implementation class to construct object with.

sycl/source/detail/graph_impl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,11 @@ modifiable_command_graph::modifiable_command_graph(
919919
: impl(std::make_shared<detail::graph_impl>(SyclContext, SyclDevice,
920920
PropList)) {}
921921

922+
modifiable_command_graph::modifiable_command_graph(
923+
const sycl::queue &SyclQueue, const sycl::property_list &PropList)
924+
: impl(std::make_shared<detail::graph_impl>(
925+
SyclQueue.get_context(), SyclQueue.get_device(), PropList)) {}
926+
922927
node modifiable_command_graph::addImpl(const std::vector<node> &Deps) {
923928
impl->throwIfGraphRecordingQueue("Explicit API \"Add()\" function");
924929
std::vector<std::shared_ptr<detail::node_impl>> DepImpls;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %{build} -o %t.out
2+
// RUN: %{run} %t.out
3+
// Extra run to check for leaks in Level Zero using UR_L0_LEAKS_DEBUG
4+
// RUN: %if level_zero %{env UR_L0_LEAKS_DEBUG=1 %{run} %t.out 2>&1 | FileCheck %s %}
5+
//
6+
// CHECK-NOT: LEAK
7+
//
8+
// TODO enable cuda once buffer issue investigated and fixed
9+
// UNSUPPORTED: cuda
10+
11+
#define GRAPH_E2E_EXPLICIT
12+
13+
#include "../Inputs/queue_constructor_buffer.cpp"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %{build} -o %t.out
2+
// RUN: %{run} %t.out
3+
// Extra run to check for leaks in Level Zero using UR_L0_LEAKS_DEBUG
4+
// RUN: %if level_zero %{env UR_L0_LEAKS_DEBUG=1 %{run} %t.out 2>&1 | FileCheck %s %}
5+
//
6+
// CHECK-NOT: LEAK
7+
8+
#define GRAPH_E2E_EXPLICIT
9+
10+
#include "../Inputs/queue_constructor_usm.cpp"
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Tests a graph created with the simplified sycl::queue constructor works
2+
// as expected.
3+
4+
#include "../graph_common.hpp"
5+
6+
int main() {
7+
queue Queue{{sycl::ext::intel::property::queue::no_immediate_command_list{}}};
8+
9+
if (!are_graphs_supported(Queue)) {
10+
return 0;
11+
}
12+
13+
using T = unsigned short;
14+
15+
std::vector<T> DataA(Size), DataB(Size), DataC(Size);
16+
17+
std::iota(DataA.begin(), DataA.end(), 1);
18+
std::iota(DataB.begin(), DataB.end(), 10);
19+
std::iota(DataC.begin(), DataC.end(), 1000);
20+
21+
std::vector<T> ReferenceA(DataA), ReferenceB(DataB), ReferenceC(DataC);
22+
calculate_reference_data(Iterations, Size, ReferenceA, ReferenceB,
23+
ReferenceC);
24+
25+
buffer<T> BufferA{DataA.data(), range<1>{DataA.size()}};
26+
BufferA.set_write_back(false);
27+
buffer<T> BufferB{DataB.data(), range<1>{DataB.size()}};
28+
BufferB.set_write_back(false);
29+
buffer<T> BufferC{DataC.data(), range<1>{DataC.size()}};
30+
BufferC.set_write_back(false);
31+
{
32+
exp_ext::command_graph Graph{
33+
Queue, {exp_ext::property::graph::assume_buffer_outlives_graph{}}};
34+
35+
// Add commands to graph
36+
add_nodes(Graph, Queue, Size, BufferA, BufferB, BufferC);
37+
38+
auto GraphExec = Graph.finalize();
39+
40+
event Event;
41+
for (unsigned n = 0; n < Iterations; n++) {
42+
Event =
43+
Queue.submit([&](handler &CGH) { CGH.ext_oneapi_graph(GraphExec); });
44+
}
45+
Queue.wait_and_throw();
46+
}
47+
48+
host_accessor HostAccA(BufferA);
49+
host_accessor HostAccB(BufferB);
50+
host_accessor HostAccC(BufferC);
51+
52+
for (size_t i = 0; i < Size; i++) {
53+
assert(check_value(i, ReferenceA[i], HostAccA[i], "HostAccA"));
54+
assert(check_value(i, ReferenceB[i], HostAccB[i], "HostAccB"));
55+
assert(check_value(i, ReferenceC[i], HostAccC[i], "HostAccC"));
56+
}
57+
58+
return 0;
59+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Tests a graph created with the simplified sycl::queue constructor works
2+
// as expected.
3+
4+
#include "../graph_common.hpp"
5+
6+
int main() {
7+
queue Queue{{sycl::ext::intel::property::queue::no_immediate_command_list{}}};
8+
9+
if (!are_graphs_supported(Queue)) {
10+
return 0;
11+
}
12+
13+
using T = int;
14+
15+
std::vector<T> DataA(Size), DataB(Size), DataC(Size);
16+
std::iota(DataA.begin(), DataA.end(), 1);
17+
std::iota(DataB.begin(), DataB.end(), 10);
18+
std::iota(DataC.begin(), DataC.end(), 1000);
19+
20+
std::vector<T> ReferenceA(DataA), ReferenceB(DataB), ReferenceC(DataC);
21+
calculate_reference_data(Iterations, Size, ReferenceA, ReferenceB,
22+
ReferenceC);
23+
24+
exp_ext::command_graph Graph{Queue};
25+
26+
T *PtrA = malloc_device<T>(Size, Queue);
27+
T *PtrB = malloc_device<T>(Size, Queue);
28+
T *PtrC = malloc_device<T>(Size, Queue);
29+
30+
Queue.copy(DataA.data(), PtrA, Size);
31+
Queue.copy(DataB.data(), PtrB, Size);
32+
Queue.copy(DataC.data(), PtrC, Size);
33+
Queue.wait_and_throw();
34+
35+
// Add commands to graph
36+
add_nodes(Graph, Queue, Size, PtrA, PtrB, PtrC);
37+
38+
auto GraphExec = Graph.finalize();
39+
40+
auto SubmitGraph = [&]() {
41+
Queue.submit([&](handler &CGH) { CGH.ext_oneapi_graph(GraphExec); });
42+
};
43+
44+
event Event;
45+
for (unsigned n = 0; n < Iterations; n++) {
46+
Event =
47+
Queue.submit([&](handler &CGH) { CGH.ext_oneapi_graph(GraphExec); });
48+
}
49+
50+
Queue.wait_and_throw();
51+
52+
Queue.copy(PtrA, DataA.data(), Size);
53+
Queue.copy(PtrB, DataB.data(), Size);
54+
Queue.copy(PtrC, DataC.data(), Size);
55+
Queue.wait_and_throw();
56+
57+
free(PtrA, Queue);
58+
free(PtrB, Queue);
59+
free(PtrC, Queue);
60+
61+
for (size_t i = 0; i < Size; i++) {
62+
assert(check_value(i, ReferenceA[i], DataA[i], "DataA"));
63+
assert(check_value(i, ReferenceB[i], DataB[i], "DataB"));
64+
assert(check_value(i, ReferenceC[i], DataC[i], "DataC"));
65+
}
66+
67+
return 0;
68+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %{build} -o %t.out
2+
// RUN: %{run} %t.out
3+
// Extra run to check for leaks in Level Zero using UR_L0_LEAKS_DEBUG
4+
// RUN: %if level_zero %{env UR_L0_LEAKS_DEBUG=1 %{run} %t.out 2>&1 | FileCheck %s %}
5+
//
6+
// CHECK-NOT: LEAK
7+
//
8+
// TODO enable cuda once buffer issue investigated and fixed
9+
// UNSUPPORTED: cuda
10+
11+
#define GRAPH_E2E_RECORD_REPLAY
12+
13+
#include "../Inputs/queue_constructor_buffer.cpp"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %{build} -o %t.out
2+
// RUN: %{run} %t.out
3+
// Extra run to check for leaks in Level Zero using UR_L0_LEAKS_DEBUG
4+
// RUN: %if level_zero %{env UR_L0_LEAKS_DEBUG=1 %{run} %t.out 2>&1 | FileCheck %s %}
5+
//
6+
// CHECK-NOT: LEAK
7+
8+
#define GRAPH_E2E_RECORD_REPLAY
9+
10+
#include "../Inputs/queue_constructor_usm.cpp"

sycl/test/abi/sycl_symbols_linux.dump

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3733,7 +3733,9 @@ _ZN4sycl3_V13ext6oneapi12experimental6detail24modifiable_command_graph24addGraph
37333733
_ZN4sycl3_V13ext6oneapi12experimental6detail24modifiable_command_graph7addImplERKSt6vectorINS3_4nodeESaIS7_EE
37343734
_ZN4sycl3_V13ext6oneapi12experimental6detail24modifiable_command_graph7addImplESt8functionIFvRNS0_7handlerEEERKSt6vectorINS3_4nodeESaISC_EE
37353735
_ZN4sycl3_V13ext6oneapi12experimental6detail24modifiable_command_graph9make_edgeERNS3_4nodeES7_
3736+
_ZN4sycl3_V13ext6oneapi12experimental6detail24modifiable_command_graphC1ERKNS0_5queueERKNS0_13property_listE
37363737
_ZN4sycl3_V13ext6oneapi12experimental6detail24modifiable_command_graphC1ERKNS0_7contextERKNS0_6deviceERKNS0_13property_listE
3738+
_ZN4sycl3_V13ext6oneapi12experimental6detail24modifiable_command_graphC2ERKNS0_5queueERKNS0_13property_listE
37373739
_ZN4sycl3_V13ext6oneapi12experimental6detail24modifiable_command_graphC2ERKNS0_7contextERKNS0_6deviceERKNS0_13property_listE
37383740
_ZN4sycl3_V13ext6oneapi12experimental9image_memC1ERKNS3_16image_descriptorERKNS0_5queueE
37393741
_ZN4sycl3_V13ext6oneapi12experimental9image_memC1ERKNS3_16image_descriptorERKNS0_6deviceERKNS0_7contextE

sycl/test/abi/sycl_symbols_windows.dump

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,7 @@
600600
??0modifiable_command_graph@detail@experimental@oneapi@ext@_V1@sycl@@QEAA@$$QEAV0123456@@Z
601601
??0modifiable_command_graph@detail@experimental@oneapi@ext@_V1@sycl@@QEAA@AEBV0123456@@Z
602602
??0modifiable_command_graph@detail@experimental@oneapi@ext@_V1@sycl@@QEAA@AEBVcontext@56@AEBVdevice@56@AEBVproperty_list@56@@Z
603+
??0modifiable_command_graph@detail@experimental@oneapi@ext@_V1@sycl@@QEAA@AEBVqueue@56@AEBVproperty_list@56@@Z
603604
??0node@experimental@oneapi@ext@_V1@sycl@@AEAA@AEBV?$shared_ptr@Vnode_impl@detail@experimental@oneapi@ext@_V1@sycl@@@std@@@Z
604605
??0node@experimental@oneapi@ext@_V1@sycl@@QEAA@$$QEAV012345@@Z
605606
??0node@experimental@oneapi@ext@_V1@sycl@@QEAA@AEBV012345@@Z

0 commit comments

Comments
 (0)