Skip to content

Commit c4b4c91

Browse files
committed
[SYCL][UR][OpenCL] allow passing events from different contexts
to urEventWait
1 parent 55fd99b commit c4b4c91

File tree

2 files changed

+109
-3
lines changed

2 files changed

+109
-3
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// RUN: %{build} -o %t.out
2+
// RUN: %{run} %t.out
3+
4+
#include <iostream>
5+
#include <sycl/sycl.hpp>
6+
#include <vector>
7+
8+
std::vector<sycl::event> submit_dependencies(sycl::queue q1, sycl::queue q2,
9+
int *mem1, int *mem2) {
10+
int delay_ops = 1024 * 1024;
11+
auto delay = [=] {
12+
volatile int value = delay_ops;
13+
while (--value)
14+
;
15+
};
16+
17+
auto ev1 =
18+
q1.parallel_for(sycl::range<1>(1024), [=]([[maybe_unused]] auto u) {
19+
delay();
20+
mem1[u.get_id()] = 1;
21+
});
22+
auto ev2 =
23+
q2.parallel_for(sycl::range<1>(1024), [=]([[maybe_unused]] auto u) {
24+
delay();
25+
mem2[u.get_id()] = 2;
26+
});
27+
28+
return {ev1, ev2};
29+
}
30+
31+
void test_host_task() {
32+
sycl::context c1{};
33+
sycl::context c2{};
34+
35+
sycl::queue q1(c1, sycl::default_selector_v);
36+
sycl::queue q2(c2, sycl::default_selector_v);
37+
38+
auto mem1 = sycl::malloc_host<int>(1024, q1);
39+
auto mem2 = sycl::malloc_host<int>(1024, q2);
40+
41+
auto events = submit_dependencies(q1, q2, mem1, mem2);
42+
43+
q2.submit([&](sycl::handler &cgh) {
44+
cgh.depends_on(events[0]);
45+
cgh.depends_on(events[1]);
46+
cgh.host_task([=]() {
47+
for (int i = 0; i < 1024; i++) {
48+
assert(mem1[i] == 1);
49+
assert(mem2[i] == 2);
50+
}
51+
});
52+
});
53+
54+
sycl::free(mem1, c1);
55+
sycl::free(mem2, c2);
56+
}
57+
58+
void test_kernel() {
59+
sycl::context c1{};
60+
sycl::context c2{};
61+
62+
sycl::queue q1(c1, sycl::default_selector_v);
63+
sycl::queue q2(c2, sycl::default_selector_v);
64+
65+
auto mem1 = sycl::malloc_device<int>(1024, q1);
66+
auto mem2 = sycl::malloc_device<int>(1024, q2);
67+
68+
auto events = submit_dependencies(q1, q2, mem1, mem2);
69+
70+
q2.submit([&](sycl::handler &cgh) {
71+
cgh.depends_on(events[0]);
72+
cgh.depends_on(events[1]);
73+
cgh.parallel_for(sycl::range<1>(1024), [=](auto item) {
74+
assert(mem1[item.get_id()] == 1);
75+
assert(mem2[item.get_id()] == 2);
76+
});
77+
});
78+
79+
sycl::free(mem1, c1);
80+
sycl::free(mem2, c2);
81+
}
82+
83+
int main() {
84+
test_host_task();
85+
test_kernel();
86+
87+
return 0;
88+
}

unified-runtime/source/adapters/opencl/event.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,29 @@ UR_APIEXPORT ur_result_t UR_APICALL urEventRetain(ur_event_handle_t hEvent) {
149149

150150
UR_APIEXPORT ur_result_t UR_APICALL
151151
urEventWait(uint32_t numEvents, const ur_event_handle_t *phEventWaitList) {
152-
std::vector<cl_event> CLEvents(numEvents);
152+
if (numEvents == 0 || !phEventWaitList) {
153+
return UR_RESULT_SUCCESS;
154+
}
155+
156+
ur_context_handle_t hContext = phEventWaitList[0]->Context;
157+
std::vector<cl_event> CLEvents;
158+
CLEvents.reserve(numEvents);
159+
160+
// clWaitForEvents can only be called on events from the same context.
161+
// If the events are from different contexts, we need to wait for each
162+
// set of events separately.
153163
for (uint32_t i = 0; i < numEvents; i++) {
154-
CLEvents[i] = phEventWaitList[i]->CLEvent;
164+
if (phEventWaitList[i]->Context != hContext) {
165+
cl_int RetErr = clWaitForEvents(CLEvents.size(), CLEvents.data());
166+
CL_RETURN_ON_FAILURE(RetErr);
167+
168+
CLEvents.clear();
169+
}
170+
171+
CLEvents.push_back(phEventWaitList[i]->CLEvent);
172+
hContext = phEventWaitList[i]->Context;
155173
}
156-
cl_int RetErr = clWaitForEvents(numEvents, CLEvents.data());
174+
cl_int RetErr = clWaitForEvents(CLEvents.size(), CLEvents.data());
157175
CL_RETURN_ON_FAILURE(RetErr);
158176
return UR_RESULT_SUCCESS;
159177
}

0 commit comments

Comments
 (0)