Skip to content

Commit 0e109f6

Browse files
lbushi25gmlueckAlexeySachkovkbenzie
authored
[SYCL] Implement sycl_ext_oneapi_prod extension (#13555)
This PR includes a preliminary implementation of the ext_oneapi_prod extension defined here: https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/supported/sycl_ext_oneapi_prod.asciidoc --------- Co-authored-by: Greg Lueck <[email protected]> Co-authored-by: Alexey Sachkov <[email protected]> Co-authored-by: Kenneth Benzie (Benie) <[email protected]>
1 parent 9ec73a2 commit 0e109f6

File tree

10 files changed

+154
-6
lines changed

10 files changed

+154
-6
lines changed

sycl/doc/extensions/proposed/sycl_ext_oneapi_prod.asciidoc renamed to sycl/doc/extensions/supported/sycl_ext_oneapi_prod.asciidoc

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,13 @@ https://github.com/intel/llvm/issues
3636

3737
== Dependencies
3838

39-
This extension is written against the SYCL 2020 revision 5 specification. All
39+
This extension is written against the SYCL 2020 revision 8 specification. All
4040
references below to the "core SYCL specification" or to section numbers in the
4141
SYCL specification refer to that revision.
4242

4343
== Status
4444

45-
This is a proposed extension specification, intended to gather community
46-
feedback. Interfaces defined in this specification may not be implemented yet
47-
or may be in a preliminary state. The specification itself may also change in
48-
incompatible ways before it is finalized. *Shipping software products should
49-
not rely on APIs defined in this specification.*
45+
This extension is implemented and fully supported by DPC++.
5046

5147
== Overview
5248

sycl/include/sycl/queue.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2590,6 +2590,11 @@ class __SYCL_EXPORT queue : public detail::OwnerLessBase<queue> {
25902590
CodeLoc);
25912591
}
25922592

2593+
/// Provides a hint to the runtime that previously issued commands to this
2594+
/// queue should begin executing once their prerequisites have been satisfied.
2595+
///
2596+
void ext_oneapi_prod();
2597+
25932598
/// Returns whether the queue is in order or OoO
25942599
///
25952600
/// Equivalent to has_property<property::queue::in_order>()

sycl/source/detail/queue_impl.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,20 @@ class queue_impl {
388388
template <typename Param>
389389
typename Param::return_type get_backend_info() const;
390390

391+
/// Provides a hint to the backend to execute previously issued commands on
392+
/// this queue. Overrides normal batching behaviour. Note that this is merely
393+
/// a hint and not a guarantee.
394+
void flush() {
395+
if (MGraph.lock()) {
396+
throw sycl::exception(make_error_code(errc::invalid),
397+
"flush cannot be called for a queue which is "
398+
"recording to a command graph.");
399+
}
400+
for (const auto &queue : MQueues) {
401+
getPlugin()->call<PiApiKind::piQueueFlush>(queue);
402+
}
403+
}
404+
391405
using SubmitPostProcessF = std::function<void(bool, bool, event &)>;
392406

393407
/// Submits a command group function object to the queue, in order to be

sycl/source/feature_test.hpp.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ inline namespace _V1 {
106106
#define SYCL_EXT_ONEAPI_PRIVATE_ALLOCA 1
107107
#define SYCL_EXT_ONEAPI_FORWARD_PROGRESS 1
108108
#define SYCL_EXT_ONEAPI_FREE_FUNCTION_KERNELS 1
109+
#define SYCL_EXT_ONEAPI_PROD 1
109110

110111
#ifndef __has_include
111112
#define __has_include(x) 0

sycl/source/queue.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,8 @@ backend queue::get_backend() const noexcept { return getImplBackend(impl); }
323323

324324
bool queue::ext_oneapi_empty() const { return impl->ext_oneapi_empty(); }
325325

326+
void queue::ext_oneapi_prod() { impl->flush(); }
327+
326328
pi_native_handle queue::getNative(int32_t &NativeHandleDesc) const {
327329
return impl->getNative(NativeHandleDesc);
328330
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// RUN: %{build} -o %t.out
2+
// RUN: %t.out
3+
4+
#include <stdlib.h>
5+
#include <sycl/sycl.hpp>
6+
#include <vector>
7+
8+
using namespace sycl;
9+
using namespace std;
10+
11+
// This test checks the ext_oneapi_prod extension. This extension introduces
12+
// only one new function, queue::ext_oneapi_prod(), which serves as a hint to
13+
// the compiler to flush the queue. Since it is simply a hint, we cannot really
14+
// test what the backend is doing but we can at least make sure that code
15+
// involving this function compiles and runs successfully in various contexts.
16+
int main() {
17+
sycl::queue q;
18+
19+
// Test on an empty queue multiple times.
20+
q.ext_oneapi_prod();
21+
q.ext_oneapi_prod();
22+
23+
// Test on a queue after we've submitted a kernel in various contexts.
24+
q.single_task([]() {});
25+
q.ext_oneapi_prod();
26+
27+
q.parallel_for(range<1>{}, [=](auto &idx) {});
28+
q.ext_oneapi_prod();
29+
q.wait();
30+
31+
// Test that the result of an in-progress addition kernel is not affected by
32+
// calling ext_oneapi_prod.
33+
srand(time(0));
34+
constexpr int N = 16;
35+
int A[N];
36+
int B[N];
37+
int add[N];
38+
int mult[N];
39+
for (int i = 0; i < N; ++i) {
40+
A[i] = rand();
41+
B[i] = rand();
42+
}
43+
{
44+
buffer<int> bufA{A, N};
45+
buffer<int> bufB{B, N};
46+
buffer<int> bufadd{add, N};
47+
48+
q.submit([&](handler &cgh) {
49+
accessor accA{bufA, cgh};
50+
accessor accB{bufB, cgh};
51+
accessor accadd{bufadd, cgh};
52+
cgh.parallel_for(N, [=](id<1> i) { accadd[i] = accA[i] + accB[i]; });
53+
});
54+
q.ext_oneapi_prod();
55+
}
56+
for (int i = 0; i < N; ++i) {
57+
assert(add[i] == (A[i] + B[i]));
58+
}
59+
60+
// Test that the result of an in-progress addition and multiplication kernel
61+
// is not affected by calling ext_oneapi_prod
62+
{
63+
buffer<int> bufA{A, N};
64+
buffer<int> bufB{B, N};
65+
buffer<int> bufadd{add, N};
66+
buffer<int> bufmult{mult, N};
67+
q.submit([&](handler &cgh) {
68+
accessor accA{bufA, cgh};
69+
accessor accB{bufB, cgh};
70+
accessor accadd{bufadd, cgh};
71+
cgh.parallel_for(N, [=](id<1> i) { accadd[i] = accA[i] + accB[i]; });
72+
});
73+
74+
q.submit([&](handler &cgh) {
75+
accessor accA{bufA, cgh};
76+
accessor accB{bufB, cgh};
77+
accessor accmult{bufmult, cgh};
78+
cgh.parallel_for(N, [=](id<1> i) { accmult[i] = accA[i] * accB[i]; });
79+
});
80+
q.ext_oneapi_prod();
81+
}
82+
for (int i = 0; i < N; ++i) {
83+
assert(add[i] == (A[i] + B[i]) && mult[i] == (A[i] * B[i]));
84+
}
85+
}

sycl/test/abi/sycl_symbols_linux.dump

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3747,6 +3747,7 @@ _ZNK4sycl3_V15queue12has_propertyINS0_8property5queue16enable_profilingEEEbv
37473747
_ZNK4sycl3_V15queue12has_propertyINS0_8property5queue4cuda18use_default_streamEEEbv
37483748
_ZNK4sycl3_V15queue12has_propertyINS0_8property5queue8in_orderEEEbv
37493749
_ZNK4sycl3_V15queue16ext_oneapi_emptyEv
3750+
_ZN4sycl3_V15queue15ext_oneapi_prodEv
37503751
_ZNK4sycl3_V15queue16get_backend_infoINS0_4info6device15backend_versionEEENS0_6detail20is_backend_info_descIT_E11return_typeEv
37513752
_ZNK4sycl3_V15queue16get_backend_infoINS0_4info6device7versionEEENS0_6detail20is_backend_info_descIT_E11return_typeEv
37523753
_ZNK4sycl3_V15queue16get_backend_infoINS0_4info8platform7versionEEENS0_6detail20is_backend_info_descIT_E11return_typeEv

sycl/test/abi/sycl_symbols_windows.dump

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4085,6 +4085,7 @@
40854085
?ext_oneapi_copy@handler@_V1@sycl@@QEAAXUimage_mem_handle@experimental@oneapi@ext@23@0AEBUimage_descriptor@56723@@Z
40864086
?ext_oneapi_copy@handler@_V1@sycl@@QEAAXUimage_mem_handle@experimental@oneapi@ext@23@PEAXAEBUimage_descriptor@56723@@Z
40874087
?ext_oneapi_copy@handler@_V1@sycl@@QEAAXUimage_mem_handle@experimental@oneapi@ext@23@V?$range@$02@23@AEBUimage_descriptor@56723@PEAX111@Z
4088+
?ext_oneapi_prod@queue@_V1@sycl@@QEAAXXZ
40884089
?ext_oneapi_copy@queue@_V1@sycl@@QEAA?AVevent@23@PEAX0AEBUimage_descriptor@experimental@oneapi@ext@23@_KAEBUcode_location@detail@23@@Z
40894090
?ext_oneapi_copy@queue@_V1@sycl@@QEAA?AVevent@23@PEAX0AEBUimage_descriptor@experimental@oneapi@ext@23@_KAEBV?$vector@Vevent@_V1@sycl@@V?$allocator@Vevent@_V1@sycl@@@std@@@std@@AEBUcode_location@detail@23@@Z
40904091
?ext_oneapi_copy@queue@_V1@sycl@@QEAA?AVevent@23@PEAX0AEBUimage_descriptor@experimental@oneapi@ext@23@_KV423@AEBUcode_location@detail@23@@Z

sycl/unittests/Extensions/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ add_sycl_unittest(ExtensionsTests OBJECT
99
OneAPISubGroupMask.cpp
1010
USMP2P.cpp
1111
CompositeDevice.cpp
12+
OneAPIProd.cpp
1213
)
1314

1415
add_subdirectory(CommandGraph)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//==-------- OneAPIProd.cpp --- sycl_ext_oneapi_prod unit tests ------------==//
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+
#include <sycl/sycl.hpp>
10+
11+
#include <helpers/PiMock.hpp>
12+
13+
#include <gtest/gtest.h>
14+
15+
using namespace sycl;
16+
17+
static bool QueueFlushed = false;
18+
19+
static pi_result redefinedQueueFlush(pi_queue Queue) {
20+
QueueFlushed = true;
21+
return PI_SUCCESS;
22+
}
23+
24+
TEST(OneAPIProdTest, PiQueueFlush) {
25+
sycl::unittest::PiMock Mock(backend::ext_oneapi_level_zero);
26+
sycl::platform Plt = Mock.getPlatform();
27+
Mock.redefine<detail::PiApiKind::piQueueFlush>(redefinedQueueFlush);
28+
context Ctx{Plt};
29+
queue Queue{Ctx, default_selector_v};
30+
Queue.ext_oneapi_prod();
31+
EXPECT_TRUE(QueueFlushed);
32+
sycl::ext::oneapi::experimental::command_graph Graph(Ctx, Queue.get_device());
33+
Graph.begin_recording(Queue);
34+
try {
35+
Queue.ext_oneapi_prod(); // flushing while graph is recording is not allowed
36+
FAIL() << "Expected exception when calling ext_oneapi_prod() during graph "
37+
"recording not seen.";
38+
} catch (exception &ex) {
39+
EXPECT_EQ(ex.code(), make_error_code(errc::invalid));
40+
}
41+
Graph.end_recording(Queue);
42+
}

0 commit comments

Comments
 (0)