Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion sycl/source/detail/queue_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -615,11 +615,17 @@ EventImplPtr queue_impl::submit_barrier_direct_impl(
/*SchedulerBypass*/ true};
}

if (EventForReuse) {
if (EventForReuse || !CallerNeedsEvent) {
// Current limitation: reusable events require scheduler bypass so that
// the barrier can be submitted directly to the backend with the reusable
// event's handle as the output event. Scheduler bypass is not possible
// when dependencies include host tasks or cross-context dependencies.
//
// This limitation applies to both: enqueue_signal_event and
// enqueue_wait_event(s).
//
// The !CallerNeedsEvent condition is used to detect the
// enqueue_wait_event(s) function calls.
throw sycl::exception(sycl::make_error_code(errc::invalid),
"An event cannot be enqueued for signaling behind "
"a command which is not enqueued in the backend.");
Comment on lines +618 to 631
Expand Down
27 changes: 27 additions & 0 deletions sycl/source/reusable_events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ __SYCL_EXPORT sycl::event make_event(const sycl::context &ctxt,

__SYCL_EXPORT void enqueue_wait_event(sycl::queue q, const event &evt) {
detail::queue_impl &QueueImpl = *sycl::detail::getSyclObjImpl(q);
detail::event_impl &EventImpl = *sycl::detail::getSyclObjImpl(evt);

// Current limitation:
// The queue and an event need to be in the same context. The reason
// is, that cross-context dependencies use host tasks, and the wait
// command might be queued in the runtime. This flow is currently
// not supported by the Reusable Events APIs.
if (&QueueImpl.getContextImpl() != &EventImpl.getContextImpl()) {
throw sycl::exception(
sycl::make_error_code(errc::invalid),
Comment thread
KseniyaTikhomirova marked this conversation as resolved.
"Not implemented yet. Event context must match the queue context.");
}
Comment on lines 62 to +74

QueueImpl.submit_barrier_direct_without_event(
sycl::span<const event>(&evt, 1), detail::CGType::BarrierWaitlist,
Expand All @@ -70,6 +82,21 @@ __SYCL_EXPORT void enqueue_wait_events(sycl::queue q,
const std::vector<event> &evts) {
detail::queue_impl &QueueImpl = *sycl::detail::getSyclObjImpl(q);

// Current limitation:
// The queue and all the events need to be in the same context. The
// reason is, that cross-context dependencies use host tasks, and the
// wait command might be queued in the runtime. This flow is currently
// not supported by the Reusable Events APIs.
for (sycl::event evt : evts) {
detail::event_impl &EventImpl = *sycl::detail::getSyclObjImpl(evt);
if (&QueueImpl.getContextImpl() != &EventImpl.getContextImpl()) {
throw sycl::exception(
sycl::make_error_code(errc::invalid),
"Not implemented yet. Context of all events must match the "
"queue context.");
}
}
Comment on lines +85 to +98

QueueImpl.submit_barrier_direct_without_event(
evts, detail::CGType::BarrierWaitlist, detail::code_location::current());
}
Expand Down
73 changes: 60 additions & 13 deletions sycl/unittests/Extensions/ReusableEvents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,9 @@ TEST_F(ReusableEventsTest, EventInDependsOn) {
Queue.wait();
}

// Cross-context events with wait
// Cross-context event with wait.
// Current limitation is that the cross-context wait
// is not supported.
TEST_F(ReusableEventsTest, CrossContextEventWait) {
mock::getCallbacks().set_replace_callback("urDeviceGet",
&redefinedUrDeviceGet);
Expand All @@ -467,23 +469,68 @@ TEST_F(ReusableEventsTest, CrossContextEventWait) {

auto event = syclex::make_event(Ctx1);

mock::getCallbacks().set_replace_callback(
"urEnqueueEventsWaitWithBarrierExt",
&redefinedUrEnqueueEventsWaitWithBarrierExt_signal);
bool exception = false;

syclex::enqueue_signal_event(Queue1, event);
// Current limiation is that an event from different context
// cannot be used with enqueue_wait_event
Comment on lines +474 to +475
try {
syclex::enqueue_wait_event(Queue2, event);
} catch (sycl::exception const &e) {
exception = true;
EXPECT_EQ(e.code(), sycl::errc::invalid);
EXPECT_STREQ(e.what(), "Not implemented yet. Event context must "
"match the queue context.");
}

EXPECT_EQ(RedefinedUrEnqueueEventsWaitWithBarrierExt_signal_counter, 1);
EXPECT_TRUE(exception);

ExpectedNumEventsInWaitList = 1;
mock::getCallbacks().set_replace_callback(
"urEnqueueEventsWaitWithBarrierExt",
&redefinedUrEnqueueEventsWaitWithBarrierExt_wait);
Queue1.wait();
Queue2.wait();
}

// Event from different context should still work with enqueue_wait_event
EXPECT_NO_THROW({ syclex::enqueue_wait_event(Queue2, event); });
Comment thread
slawekptak marked this conversation as resolved.
// Cross-context events with wait (multiple events).
// Current limitation is that the cross-context wait
// is not supported.
TEST_F(ReusableEventsTest, CrossContextEventsWait) {
mock::getCallbacks().set_replace_callback("urDeviceGet",
&redefinedUrDeviceGet);
mock::getCallbacks().set_replace_callback("urDeviceRelease",
&redefinedUrDeviceRelease);

EXPECT_EQ(RedefinedUrEnqueueEventsWaitWithBarrierExt_wait_counter, 1);
sycl::platform Plt = sycl::platform();
auto Devices = Plt.get_devices();

if (Devices.size() < 2) {
GTEST_SKIP() << "Need at least 2 devices for this test";
}

const sycl::device Dev1 = Devices[0];
const sycl::device Dev2 = Devices[1];
sycl::context Ctx1{Dev1};
sycl::context Ctx2{Dev2};

sycl::queue Queue1{Ctx1, Dev1};
sycl::queue Queue2{Ctx2, Dev2};

auto event1 = syclex::make_event(Ctx1);
auto event2 = syclex::make_event(Ctx1);

std::vector<sycl::event> events{event1, event2};

bool exception = false;

// Current limiation is that an event from different context
// cannot be used with enqueue_wait_event
Comment on lines +522 to +523
try {
syclex::enqueue_wait_events(Queue2, events);
} catch (sycl::exception const &e) {
exception = true;
EXPECT_EQ(e.code(), sycl::errc::invalid);
EXPECT_STREQ(e.what(), "Not implemented yet. Context of all events must "
"match the queue context.");
}

EXPECT_TRUE(exception);

Queue1.wait();
Queue2.wait();
Expand Down
Loading