Skip to content

Commit 65849fd

Browse files
[SYCL][Docs] Allow discarded events case for ext_oneapi_get_last_event (#15638)
This commit changes the behavior for queue::ext_oneapi_get_last_event when the queue either does not currently have a last event or the last event was discarded. In these cases, the implementation will now insert a marker event at the end of the queue which signifies the work related to the last command in the queue. Additionally, this allows us to relax the requirements for the extension to now allow it to be used on queues where discarding of events is enabled. Signed-off-by: Larsen, Steffen <[email protected]>
1 parent cfd7407 commit 65849fd

File tree

6 files changed

+96
-23
lines changed

6 files changed

+96
-23
lines changed

sycl/doc/extensions/experimental/sycl_ext_oneapi_in_order_queue_events.asciidoc

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,6 @@ copy of the event that was passed to `ext_oneapi_set_external_event()`.
122122

123123
Calls to this member function throw a `sycl::exception` with `errc::invalid` if
124124
the queue does not have the `property::queue::in_order` property.
125-
126-
Calls to this member function throw a `sycl::exception` with `errc::invalid` if
127-
the queue has the `ext::oneapi::property::queue::discard_events` property from
128-
the
129-
link:../supported/sycl_ext_oneapi_discard_queue_events.asciidoc[sycl_ext_oneapi_discard_queue_events extension].
130125

131126
a|
132127
[source, c++]
@@ -154,10 +149,5 @@ undefined.
154149

155150
Calls to this member function throw a `sycl::exception` with `errc::invalid` if
156151
the queue does not have the `property::queue::in_order` property.
157-
158-
Calls to this member function throw a `sycl::exception` with `errc::invalid` if
159-
the queue has the `ext::oneapi::property::queue::discard_events` property from
160-
the
161-
link:../supported/sycl_ext_oneapi_discard_queue_events.asciidoc[sycl_ext_oneapi_discard_queue_events extension].
162152
|====
163153
--

sycl/source/detail/queue_impl.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,18 @@ class queue_impl {
710710

711711
const property_list &getPropList() const { return MPropList; }
712712

713+
/// Inserts a marker event at the end of the queue. Waiting for this marker
714+
/// will wait for the completion of all work in the queue at the time of the
715+
/// insertion, but will not act as a barrier unless the queue is in-order.
716+
EventImplPtr insertMarkerEvent(const std::shared_ptr<queue_impl> &Self) {
717+
auto ResEvent = std::make_shared<detail::event_impl>(Self);
718+
ur_event_handle_t UREvent = nullptr;
719+
getAdapter()->call<UrApiKind::urEnqueueEventsWait>(getHandleRef(), 0,
720+
nullptr, &UREvent);
721+
ResEvent->setHandle(UREvent);
722+
return ResEvent;
723+
}
724+
713725
protected:
714726
event discard_or_return(const event &Event);
715727

sycl/source/queue.cpp

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -361,24 +361,22 @@ event queue::ext_oneapi_get_last_event() const {
361361
throw sycl::exception(
362362
make_error_code(errc::invalid),
363363
"ext_oneapi_get_last_event() can only be called on in-order queues.");
364-
if (impl->MDiscardEvents)
365-
throw sycl::exception(
366-
make_error_code(errc::invalid),
367-
"ext_oneapi_get_last_event() cannot be called on queues with the "
368-
"ext::oneapi::property::queue::discard_events property.");
369-
return impl->getLastEvent();
364+
365+
event LastEvent = impl->getLastEvent();
366+
// If the last event was discarded or a NOP, we insert a marker to represent
367+
// an event at end.
368+
auto LastEventImpl = detail::getSyclObjImpl(LastEvent);
369+
if (LastEventImpl->isDiscarded() || LastEventImpl->isNOP())
370+
LastEvent =
371+
detail::createSyclObjFromImpl<event>(impl->insertMarkerEvent(impl));
372+
return LastEvent;
370373
}
371374

372375
void queue::ext_oneapi_set_external_event(const event &external_event) {
373376
if (!is_in_order())
374377
throw sycl::exception(make_error_code(errc::invalid),
375378
"ext_oneapi_set_external_event() can only be called "
376379
"on in-order queues.");
377-
if (impl->MDiscardEvents)
378-
throw sycl::exception(
379-
make_error_code(errc::invalid),
380-
"ext_oneapi_set_external_event() cannot be called on queues with the "
381-
"ext::oneapi::property::queue::discard_events property.");
382380
return impl->setExternalEvent(external_event);
383381
}
384382

sycl/test-e2e/InOrderEventsExt/get_last_event.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// call to ext_oneapi_set_external_event.
1414

1515
#include <sycl/detail/core.hpp>
16+
#include <sycl/ext/oneapi/experimental/enqueue_functions.hpp>
1617
#include <sycl/properties/all_properties.hpp>
1718
#include <sycl/usm.hpp>
1819

@@ -33,11 +34,18 @@ int main() {
3334

3435
int Failed = 0;
3536

36-
Failed += Check(Q, "single_task", [&]() { return Q.single_task([]() {}); });
37+
// Check that a valid event is returned on the empty queue.
38+
Q.ext_oneapi_get_last_event().wait();
39+
40+
// Check that a valid event is returned after enqueuing work without events.
41+
sycl::ext::oneapi::experimental::single_task(Q, []() {});
42+
Q.ext_oneapi_get_last_event().wait();
3743

44+
// Check event equivalences - This is an implementation detail, but useful
45+
// for checking behavior.
46+
Failed += Check(Q, "single_task", [&]() { return Q.single_task([]() {}); });
3847
Failed += Check(Q, "parallel_for",
3948
[&]() { return Q.parallel_for(32, [](sycl::id<1>) {}); });
40-
4149
Failed += Check(Q, "host_task", [&]() {
4250
return Q.submit([&](sycl::handler &CGH) { CGH.host_task([]() {}); });
4351
});

sycl/unittests/Extensions/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ add_sycl_unittest(ExtensionsTests OBJECT
1515
ProfilingTag.cpp
1616
KernelProperties.cpp
1717
NoDeviceIPVersion.cpp
18+
GetLastEvent.cpp
1819
)
1920

2021
add_subdirectory(CommandGraph)
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//==------------------------- GetLastEvent.cpp -----------------------------==//
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+
// Tests the behavior of queue::ext_oneapi_get_last_event.
9+
10+
#include <detail/event_impl.hpp>
11+
#include <gtest/gtest.h>
12+
#include <helpers/TestKernel.hpp>
13+
#include <helpers/UrMock.hpp>
14+
#include <sycl/ext/oneapi/experimental/enqueue_functions.hpp>
15+
#include <sycl/properties/queue_properties.hpp>
16+
#include <sycl/queue.hpp>
17+
18+
using namespace sycl;
19+
20+
thread_local ur_event_handle_t MarkerEventLatest = nullptr;
21+
static ur_result_t redefinedEnqueueEventsWaitAfter(void *pParams) {
22+
auto params = *static_cast<ur_enqueue_events_wait_params_t *>(pParams);
23+
MarkerEventLatest = **(params.pphEvent);
24+
return UR_RESULT_SUCCESS;
25+
}
26+
static ur_result_t redefinedEventRelease(void *) { return UR_RESULT_SUCCESS; }
27+
28+
TEST(GetLastEventEmptyQueue, CheckEmptyQueueLastEvent) {
29+
unittest::UrMock<> Mock;
30+
platform Plt = sycl::platform();
31+
32+
MarkerEventLatest = nullptr;
33+
mock::getCallbacks().set_after_callback("urEnqueueEventsWait",
34+
&redefinedEnqueueEventsWaitAfter);
35+
mock::getCallbacks().set_before_callback("urEventRelease",
36+
&redefinedEventRelease);
37+
38+
queue Q{property::queue::in_order{}};
39+
event E = Q.ext_oneapi_get_last_event();
40+
ur_event_handle_t UREvent = detail::getSyclObjImpl(E)->getHandle();
41+
ASSERT_NE(MarkerEventLatest, ur_event_handle_t{nullptr});
42+
ASSERT_EQ(UREvent, MarkerEventLatest);
43+
}
44+
45+
TEST(GetLastEventEmptyQueue, CheckEventlessWorkQueue) {
46+
unittest::UrMock<> Mock;
47+
platform Plt = sycl::platform();
48+
49+
MarkerEventLatest = nullptr;
50+
mock::getCallbacks().set_after_callback("urEnqueueEventsWait",
51+
&redefinedEnqueueEventsWaitAfter);
52+
mock::getCallbacks().set_before_callback("urEventRelease",
53+
&redefinedEventRelease);
54+
55+
queue Q{property::queue::in_order{}};
56+
57+
// The following single_task does not return an event, so it is expected that
58+
// the last event query creates a new marker event.
59+
sycl::ext::oneapi::experimental::single_task<TestKernel<>>(Q, []() {});
60+
event E = Q.ext_oneapi_get_last_event();
61+
ur_event_handle_t UREvent = detail::getSyclObjImpl(E)->getHandle();
62+
ASSERT_NE(MarkerEventLatest, ur_event_handle_t{nullptr});
63+
ASSERT_EQ(UREvent, MarkerEventLatest);
64+
}

0 commit comments

Comments
 (0)