Skip to content

Commit 9f44b8e

Browse files
authored
[SYCL][Graph] E2E test updating a SPIR-V Kernel (#13890)
Add an Graph E2E test which checks for updating an accessor argument to a kernel created from SPIR-V. `update_with_indices_accessor.spv` was created by using `-fsycl-dump-device-code` on existing E2E test `update_with_indices_accessor.cpp`, and can be dissembled using `spirv-dis` if anyone is interested in looking at it further.
1 parent 46571e3 commit 9f44b8e

File tree

5 files changed

+101
-27
lines changed

5 files changed

+101
-27
lines changed
Binary file not shown.

sycl/test-e2e/Graph/Inputs/kernel_bundle_spirv.cpp

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,8 @@
33
// are identical to the ones used in KernelCompiler/Kernels/kernels.spv
44

55
#include "../graph_common.hpp"
6-
#include <fstream>
7-
8-
sycl::kernel_bundle<sycl::bundle_state::executable>
9-
loadKernelsFromFile(sycl::queue &Q, std::string FileName) {
10-
11-
// Read the SPIR-V module from disk.
12-
std::ifstream SpvStream(FileName, std::ios::binary);
13-
SpvStream.seekg(0, std::ios::end);
14-
size_t sz = SpvStream.tellg();
15-
SpvStream.seekg(0);
16-
std::vector<std::byte> Spv(sz);
17-
SpvStream.read(reinterpret_cast<char *>(Spv.data()), sz);
18-
19-
// Create a kernel bundle from the binary SPIR-V.
20-
sycl::kernel_bundle<sycl::bundle_state::ext_oneapi_source> KernelBundleSrc =
21-
exp_ext::create_kernel_bundle_from_source(
22-
Q.get_context(), exp_ext::source_language::spirv, Spv);
23-
24-
// Build the SPIR-V module for our device.
25-
sycl::kernel_bundle<sycl::bundle_state::executable> KernelBundleExe =
26-
exp_ext::build(KernelBundleSrc);
27-
return KernelBundleExe;
28-
}
296

307
int main(int, char **argv) {
31-
328
const sycl::device Dev{sycl::default_selector_v};
339
const sycl::context Ctx{Dev};
3410

sycl/test-e2e/Graph/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ option `config.required_features` to the graph aspect required to run the tests:
1616

1717
Most of the tests are written in a similar manner to other `e2e` tests. The
1818
exception to this are tests in the `Inputs` directory which are meant to be used
19-
as inputs to other tests.
19+
as inputs to other tests. The `Kernels` subdirectory of `Inputs` contains SPIR-V
20+
kernels for testing. These can be generated from SYCL kernels by using the
21+
`-fsycl-dump-device-code=<dir>` option to the DPC++ compiler.
2022

2123
Often, the same feature, needs to be tested for both the `Explicit`
2224
and `Record and Replay` APIs. To avoid code duplication, such tests are added to
@@ -29,7 +31,7 @@ common code.
2931

3032
The other directories are used to group similar tests together. Tests that
3133
require a specific `aspect` are also grouped together in order to use the
32-
`lit.local.cfg` file. Directories might themselves contain subdirectories named
34+
`lit.local.cfg` file. Directories might themselves contain subdirectories named
3335
`Explicit` and `RecordReplay` if they make use of the framework described above.
3436

3537
In addition, in order to help identify specific tests, the matching files
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// RUN: %{build} -o %t.out
2+
// RUN: %{run} %t.out %S/../Inputs/Kernels/update_with_indices_accessor.spv
3+
// Extra run to check for leaks in Level Zero using UR_L0_LEAKS_DEBUG
4+
// RUN: %if level_zero %{env SYCL_PI_LEVEL_ZERO_USE_IMMEDIATE_COMMANDLISTS=0 %{l0_leak_check} %{run} %t.out %S/../Inputs/Kernels/update_with_indices_accessor.spv 2>&1 | FileCheck %s --implicit-check-not=LEAK %}
5+
// Extra run to check for immediate-command-list in Level Zero
6+
// RUN: %if level_zero %{env SYCL_PI_LEVEL_ZERO_USE_IMMEDIATE_COMMANDLISTS=1 %{l0_leak_check} %{run} %t.out %S/../Inputs/Kernels/update_with_indices_accessor.spv 2>&1 | FileCheck %s --implicit-check-not=LEAK %}
7+
8+
// REQUIRES: level_zero
9+
10+
// Tests updating an accessor argument to a graph node created from SPIR-V
11+
// using index-based explicit update
12+
13+
#include "../graph_common.hpp"
14+
15+
int main(int, char **argv) {
16+
queue Queue{};
17+
sycl::kernel_bundle KernelBundle = loadKernelsFromFile(Queue, argv[1]);
18+
const auto getKernel =
19+
[](sycl::kernel_bundle<sycl::bundle_state::executable> &bundle,
20+
const std::string &name) {
21+
return bundle.ext_oneapi_get_kernel(name);
22+
};
23+
24+
kernel kernel = getKernel(
25+
KernelBundle, "_ZTSZZ4mainENKUlRN4sycl3_V17handlerEE_clES2_EUlvE_");
26+
27+
const size_t N = 1024;
28+
29+
exp_ext::command_graph Graph{
30+
Queue.get_context(),
31+
Queue.get_device(),
32+
{exp_ext::property::graph::assume_buffer_outlives_graph{}}};
33+
std::vector<int> HostDataA(N, 0);
34+
std::vector<int> HostDataB(N, 0);
35+
36+
buffer BufA{HostDataA};
37+
buffer BufB{HostDataB};
38+
BufA.set_write_back(false);
39+
BufB.set_write_back(false);
40+
// Initial accessor for use in kernel and dynamic parameter
41+
auto Acc = BufA.get_access();
42+
exp_ext::dynamic_parameter InputParam(Graph, Acc);
43+
44+
auto KernelNode = Graph.add([&](handler &cgh) {
45+
cgh.require(InputParam);
46+
cgh.set_arg(0, InputParam);
47+
cgh.single_task(kernel);
48+
});
49+
50+
auto ExecGraph = Graph.finalize(exp_ext::property::graph::updatable{});
51+
52+
// BufA should be filled with values
53+
Queue.ext_oneapi_graph(ExecGraph).wait();
54+
55+
Queue.copy(BufA.get_access(), HostDataA.data()).wait();
56+
Queue.copy(BufB.get_access(), HostDataB.data()).wait();
57+
for (size_t i = 0; i < N; i++) {
58+
assert(HostDataA[i] == i);
59+
assert(HostDataB[i] == 0);
60+
}
61+
62+
// Swap BufB to be the input
63+
InputParam.update(BufB.get_access());
64+
ExecGraph.update(KernelNode);
65+
Queue.ext_oneapi_graph(ExecGraph).wait();
66+
67+
Queue.copy(BufA.get_access(), HostDataA.data()).wait();
68+
Queue.copy(BufB.get_access(), HostDataB.data()).wait();
69+
for (size_t i = 0; i < N; i++) {
70+
assert(HostDataA[i] == i);
71+
assert(HostDataB[i] == i);
72+
}
73+
return 0;
74+
}

sycl/test-e2e/Graph/graph_common.hpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
#include <sycl/ext/oneapi/experimental/graph.hpp>
55

66
#include <condition_variable> // std::conditional_variable
7-
#include <mutex> // std::mutex, std::unique_lock
7+
#include <fstream>
8+
#include <mutex> // std::mutex, std::unique_lock
89
#include <numeric>
910

1011
// Test constants.
@@ -458,3 +459,24 @@ bool inline check_value(const size_t index, const T &Ref, const T &Got,
458459

459460
return true;
460461
}
462+
463+
kernel_bundle<bundle_state::executable>
464+
loadKernelsFromFile(queue &Q, std::string FileName) {
465+
// Read the SPIR-V module from disk.
466+
std::ifstream SpvStream(FileName, std::ios::binary);
467+
SpvStream.seekg(0, std::ios::end);
468+
size_t sz = SpvStream.tellg();
469+
SpvStream.seekg(0);
470+
std::vector<std::byte> Spv(sz);
471+
SpvStream.read(reinterpret_cast<char *>(Spv.data()), sz);
472+
473+
// Create a kernel bundle from the binary SPIR-V.
474+
kernel_bundle<bundle_state::ext_oneapi_source> KernelBundleSrc =
475+
exp_ext::create_kernel_bundle_from_source(
476+
Q.get_context(), exp_ext::source_language::spirv, Spv);
477+
478+
// Build the SPIR-V module for our device.
479+
kernel_bundle<bundle_state::executable> KernelBundleExe =
480+
exp_ext::build(KernelBundleSrc);
481+
return KernelBundleExe;
482+
}

0 commit comments

Comments
 (0)