Skip to content

[SYCL][Docs] Make external events wait with queue #12766

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 22, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ This is equivalent to calling `handler::depends_on()` in a command submission
with the `externalEvent` from the most recent call to this member function since
the previous command submission to the same queue.

If `queue::wait()` or `queue::wait_and_throw()` is called prior to any command
submission following a call to this member function, `externalEvent.wait()` is
called and `externalEvent` will not be a dependency on the next command
submitted to the queue.

Calls to this member function throw a `sycl::exception` with `errc::invalid` if
the queue does not have the `property::queue::in_order` property.

Expand Down
5 changes: 5 additions & 0 deletions sycl/source/detail/queue_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,11 @@ void queue_impl::wait(const detail::code_location &CodeLoc) {
for (const EventImplPtr &Event : StreamsServiceEvents)
Event->wait(Event);

// If there is an external event set, we need to wait on it.
std::optional<event> ExternalEvent = popExternalEvent();
if (ExternalEvent)
ExternalEvent->wait();

#ifdef XPTI_ENABLE_INSTRUMENTATION
instrumentationEpilog(TelemetryEvent, Name, StreamID, IId);
#endif
Expand Down
62 changes: 54 additions & 8 deletions sycl/test-e2e/InOrderEventsExt/set_external_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,13 @@

constexpr size_t N = 1024;

int main() {
sycl::context Ctx;
sycl::device Dev = Ctx.get_devices()[0];

sycl::queue Q1{Ctx, Dev, {sycl::property::queue::in_order{}}};
sycl::queue Q2{Ctx, Dev, {sycl::property::queue::in_order{}}};
int check_work(sycl::queue &Q1, sycl::queue &Q2) {
std::cout << "Checking ext_oneapi_set_external_event for a workload."
<< std::endl;

sycl::buffer<int> DevDataBuf{sycl::range{N}};
sycl::accessor DevData{DevDataBuf};
int *HostData = (int *)malloc(N * sizeof(int) * 10);
int *HostData = new int[N * 10];

for (size_t I = 0; I < 10; ++I) {
Q1.fill(DevData, 0);
Expand Down Expand Up @@ -52,6 +49,55 @@ int main() {
}
}
}
free(HostData);
delete[] HostData;
return Failures;
}

int check_wait(sycl::queue &Q1, sycl::queue &Q2) {
std::cout << "Checking ext_oneapi_set_external_event with wait on queue."
<< std::endl;

sycl::buffer<int> DevDataBuf{sycl::range{N}};
sycl::accessor DevData{DevDataBuf};
int *HostData = new int[N];

Q1.fill(DevData, 0);
for (size_t I = 0; I < 10; ++I) {
Q1.submit([&](sycl::handler &h) {
h.require(DevData);
h.parallel_for(N, [=](sycl::item<1> Idx) { ++DevData[Idx]; });
});
}
sycl::event E = Q1.copy(DevData, HostData);

Q2.ext_oneapi_set_external_event(E);
Q2.wait_and_throw();

int Failures = 0;
for (size_t I = 0; I < N; ++I) {
int Expected = 10;
int Actual = HostData[I];
if (Expected != Actual) {
std::cout << "Result not matching the expected value at index " << I
<< ": " << Expected << " != " << Actual << std::endl;
++Failures;
}
}
delete[] HostData;
return Failures;
}

int main() {
sycl::context Ctx;
sycl::device Dev = Ctx.get_devices()[0];

sycl::queue Q1{Ctx, Dev, {sycl::property::queue::in_order{}}};
sycl::queue Q2{Ctx, Dev, {sycl::property::queue::in_order{}}};

int Failures = 0;

Failures += check_work(Q1, Q2);
Failures += check_wait(Q1, Q2);

return Failures;
}