Skip to content

Commit a30775d

Browse files
authored
[SYCL] Implement sycl_khr_queue_empty_query (#18308)
Implement `khr_empty()` under `sycl_khr_queue_empty_query` (see KhronosGroup/SYCL-Docs#700), which is essentially the same as `ext_oneapi_empty()` under `sycl_ext_oneapi_queue_empty` (https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/supported/sycl_ext_oneapi_queue_empty.asciidoc), and create respective test cases. Note: the change of adding `__DPCPP_ENABLE_UNFINISHED_KHR_EXTENSIONS` in `sycl/source/CMakeLists.txt` is to make sure `khr_empty`'s implementation get successfully compiled when compiling runtime. (Otherwise there will be a "no declaration matches" error since the declaration for `khr_empty` in `sycl/include/sycl/queue.hpp` is guarded under `#ifdef __DPCPP_ENABLE_UNFINISHED_KHR_EXTENSIONS`) --------- Signed-off-by: Hu, Peisen <[email protected]>
1 parent 1e9c41d commit a30775d

11 files changed

+186
-4
lines changed

sycl/include/sycl/queue.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3541,12 +3541,20 @@ class __SYCL_EXPORT queue : public detail::OwnerLessBase<queue> {
35413541
/// \return the backend associated with this queue.
35423542
backend get_backend() const noexcept;
35433543

3544-
/// Allows to check status of the queue (completed vs noncompleted).
3544+
/// Allows to check status of the queue (completed vs incomplete).
35453545
///
35463546
/// \return returns true if all enqueued commands in the queue have been
35473547
/// completed, otherwise returns false.
35483548
bool ext_oneapi_empty() const;
35493549

3550+
/// Allows to check status of the queue (completed vs incomplete).
3551+
///
3552+
/// \return returns true if all enqueued commands in the queue have been
3553+
/// completed, otherwise returns false.
3554+
#ifdef __DPCPP_ENABLE_UNFINISHED_KHR_EXTENSIONS
3555+
bool khr_empty() const;
3556+
#endif
3557+
35503558
ur_native_handle_t getNative(int32_t &NativeHandleDesc) const;
35513559

35523560
std::optional<event> ext_oneapi_get_last_event() const {

sycl/source/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ function(add_sycl_rt_library LIB_NAME LIB_OBJ_NAME)
5050
target_compile_definitions(
5151
${LIB_OBJ_NAME}
5252
PRIVATE
53+
__DPCPP_ENABLE_UNFINISHED_KHR_EXTENSIONS
5354
__SYCL_INTERNAL_API
5455
SYCL2020_DISABLE_DEPRECATION_WARNINGS
5556
$<$<BOOL:${MSVC}>:__SYCL_BUILD_SYCL_DLL>

sycl/source/detail/queue_impl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -756,7 +756,7 @@ ur_native_handle_t queue_impl::getNative(int32_t &NativeHandleDesc) const {
756756
return Handle;
757757
}
758758

759-
bool queue_impl::ext_oneapi_empty() const {
759+
bool queue_impl::queue_empty() const {
760760
// If we have in-order queue where events are not discarded then just check
761761
// the status of the last event.
762762
if (isInOrder() && !MDiscardEvents) {

sycl/source/detail/queue_impl.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ class queue_impl {
592592
MStreamsServiceEvents.push_back(Event);
593593
}
594594

595-
bool ext_oneapi_empty() const;
595+
bool queue_empty() const;
596596

597597
event memcpyToDeviceGlobal(const std::shared_ptr<queue_impl> &Self,
598598
void *DeviceGlobalPtr, const void *Src,

sycl/source/queue.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,9 @@ bool queue::is_in_order() const {
412412

413413
backend queue::get_backend() const noexcept { return getImplBackend(impl); }
414414

415-
bool queue::ext_oneapi_empty() const { return impl->ext_oneapi_empty(); }
415+
bool queue::ext_oneapi_empty() const { return impl->queue_empty(); }
416+
417+
bool queue::khr_empty() const { return impl->queue_empty(); }
416418

417419
void queue::ext_oneapi_prod() { impl->flush(); }
418420

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// RUN: %{build} -o %t.out
2+
// RUN: %{run} %t.out
3+
4+
// Test checks that queue::khr_empty() returns status of the in-order queue.
5+
6+
#define __DPCPP_ENABLE_UNFINISHED_KHR_EXTENSIONS
7+
8+
#include <sycl/detail/core.hpp>
9+
#include <sycl/properties/all_properties.hpp>
10+
#include <sycl/usm.hpp>
11+
12+
#include <chrono>
13+
#include <thread>
14+
15+
static void CheckArray(int *x, size_t buffer_size, int expected) {
16+
for (size_t i = 0; i < buffer_size; ++i) {
17+
assert(x[i] == expected);
18+
}
19+
}
20+
21+
using namespace sycl;
22+
23+
void TestFunc(queue &Q) {
24+
static constexpr int Size = 100;
25+
26+
assert(Q.khr_empty() && "Queue is expected to be empty");
27+
28+
int *X = malloc_host<int>(Size, Q);
29+
int *Y = malloc_host<int>(Size, Q);
30+
31+
auto FillEv = Q.fill(X, 99, Size);
32+
auto SingleTaskEv = Q.submit([&](handler &CGH) {
33+
auto SingleTask = [=] {
34+
for (int I = 0; I < Size; I++)
35+
X[I] += 1;
36+
};
37+
CGH.single_task(SingleTask);
38+
});
39+
auto MemCpyEv = Q.copy(X, Y, Size);
40+
constexpr int NumIter = 5;
41+
for (int I = 0; I < NumIter; I++) {
42+
Q.submit([&](handler &CGH) {
43+
CGH.parallel_for<class Kernel1>(sycl::range<1>(Size),
44+
[=](sycl::id<1> WI) { Y[WI] *= 2; });
45+
});
46+
}
47+
48+
// Wait a bit to give a chance for tasks to complete.
49+
std::this_thread::sleep_for(std::chrono::milliseconds(500));
50+
51+
// We expect that all submitted tasks are finished if khr_empty is true.
52+
if (Q.khr_empty())
53+
CheckArray(Y, Size, 3200);
54+
55+
Q.wait();
56+
57+
// After synchronization queue must be empty.
58+
assert(Q.khr_empty() && "Queue is expected to be empty");
59+
60+
free(X, Q);
61+
free(Y, Q);
62+
}
63+
64+
int main() {
65+
// Test in-order queue.
66+
queue Q1{property::queue::in_order()};
67+
TestFunc(Q1);
68+
69+
// Test in-order queue with discard_events property.
70+
sycl::property_list Props{
71+
property::queue::in_order{},
72+
sycl::ext::oneapi::property::queue::discard_events{}};
73+
queue Q2{Props};
74+
75+
bool ExceptionThrown = false;
76+
try {
77+
TestFunc(Q2);
78+
} catch (sycl::exception &E) {
79+
ExceptionThrown = true;
80+
}
81+
82+
// Feature is not supported for OpenCL, exception must be thrown.
83+
if (Q2.get_device().get_backend() == backend::opencl)
84+
return ExceptionThrown ? 0 : -1;
85+
86+
return 0;
87+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// RUN: %{build} -o %t.out
2+
// RUN: %{run} %t.out
3+
4+
// Test checks that queue::khr_empty() returns status of the out-of-order
5+
// queue.
6+
7+
#define __DPCPP_ENABLE_UNFINISHED_KHR_EXTENSIONS
8+
9+
#include <sycl/detail/core.hpp>
10+
#include <sycl/usm.hpp>
11+
12+
#include <chrono>
13+
#include <thread>
14+
15+
static void CheckArray(int *x, size_t buffer_size, int expected) {
16+
for (size_t i = 0; i < buffer_size; ++i) {
17+
assert(x[i] == expected);
18+
}
19+
}
20+
21+
using namespace sycl;
22+
23+
void TestFunc(queue &Q) {
24+
static constexpr int Size = 100;
25+
26+
assert(Q.khr_empty() && "Queue is expected to be empty");
27+
28+
int *X = malloc_host<int>(Size, Q);
29+
int *Y = malloc_host<int>(Size, Q);
30+
31+
auto FillEv = Q.fill(X, 99, Size);
32+
auto HostEv = Q.submit([&](handler &CGH) {
33+
CGH.depends_on(FillEv);
34+
auto HostTask = [=] {
35+
for (int I = 0; I < Size; I++)
36+
X[I] += 1;
37+
};
38+
CGH.host_task(HostTask);
39+
});
40+
auto MemCpyEv = Q.copy(X, Y, Size, {HostEv});
41+
constexpr int NumIter = 5;
42+
for (int I = 0; I < NumIter; I++) {
43+
Q.submit([&](handler &CGH) {
44+
CGH.depends_on(MemCpyEv);
45+
CGH.parallel_for<class Kernel1>(
46+
sycl::range<1>(Size / NumIter),
47+
[=](sycl::id<1> WI) { Y[WI + I * Size / NumIter] *= 2; });
48+
});
49+
}
50+
51+
// Wait a bit to give a chance for tasks to complete.
52+
std::this_thread::sleep_for(std::chrono::milliseconds(500));
53+
54+
// We expect that all submitted tasks are finished if khr_empty is true.
55+
if (Q.khr_empty())
56+
CheckArray(Y, Size, 200);
57+
58+
Q.wait();
59+
60+
// After synchronization queue must be empty.
61+
assert(Q.khr_empty() && "Queue is expected to be empty");
62+
63+
free(X, Q);
64+
free(Y, Q);
65+
}
66+
67+
int main() {
68+
queue Q;
69+
70+
bool ExceptionThrown = false;
71+
try {
72+
TestFunc(Q);
73+
} catch (sycl::exception &E) {
74+
ExceptionThrown = true;
75+
}
76+
77+
// Feature is not supported for OpenCL, exception must be thrown.
78+
if (Q.get_device().get_backend() == backend::opencl)
79+
return ExceptionThrown ? 0 : -1;
80+
81+
return 0;
82+
}

sycl/test/abi/sycl_symbols_linux.dump

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3708,6 +3708,7 @@ _ZNK4sycl3_V15queue8get_infoINS0_4info5queue15reference_countEEENS0_6detail18is_
37083708
_ZNK4sycl3_V15queue8get_infoINS0_4info5queue6deviceEEENS0_6detail18is_queue_info_descIT_E11return_typeEv
37093709
_ZNK4sycl3_V15queue8get_infoINS0_4info5queue7contextEEENS0_6detail18is_queue_info_descIT_E11return_typeEv
37103710
_ZNK4sycl3_V15queue9getNativeERi
3711+
_ZNK4sycl3_V15queue9khr_emptyEv
37113712
_ZNK4sycl3_V16ONEAPI15filter_selector13select_deviceEv
37123713
_ZNK4sycl3_V16ONEAPI15filter_selector5resetEv
37133714
_ZNK4sycl3_V16ONEAPI15filter_selectorclERKNS0_6deviceE

sycl/test/abi/sycl_symbols_windows.dump

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4251,6 +4251,7 @@
42514251
?is_in_order@queue@_V1@sycl@@QEBA_NXZ
42524252
?is_specialization_constant_set@kernel_bundle_plain@detail@_V1@sycl@@IEBA_NPEBD@Z
42534253
?join_impl@detail@_V1@sycl@@YA?AV?$shared_ptr@Vkernel_bundle_impl@detail@_V1@sycl@@@std@@AEBV?$vector@V?$shared_ptr@Vkernel_bundle_impl@detail@_V1@sycl@@@std@@V?$allocator@V?$shared_ptr@Vkernel_bundle_impl@detail@_V1@sycl@@@std@@@2@@5@W4bundle_state@23@@Z
4254+
?khr_empty@queue@_V1@sycl@@QEBA_NXZ
42544255
?khr_get_default_context@platform@_V1@sycl@@QEBA?AVcontext@23@XZ
42554256
?lgamma_r_impl@detail@_V1@sycl@@YA?AVhalf@half_impl@123@V45123@PEAH@Z
42564257
?lgamma_r_impl@detail@_V1@sycl@@YAMMPEAH@Z

0 commit comments

Comments
 (0)