Skip to content

Commit 4feca82

Browse files
igchoraarongreig
andauthored
[SYCL][UR][OpenCL] Implement partial support for UR_QUEUE_INFO_EMPTY (#18601)
By storing last event in the queue. This only works for in-order queues and when last enqueued operation had signalEvent set. Otherwise UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION is returned. --------- Co-authored-by: aarongreig <[email protected]>
1 parent d33426f commit 4feca82

File tree

8 files changed

+56
-42
lines changed

8 files changed

+56
-42
lines changed

sycl/source/detail/queue_impl.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -499,8 +499,7 @@ event queue_impl::submitMemOpHelper(const std::shared_ptr<queue_impl> &Self,
499499
}
500500
}
501501

502-
if (isInOrder() &&
503-
(!isNoEventsMode || MContext->getBackend() == backend::opencl)) {
502+
if (isInOrder() && !isNoEventsMode) {
504503
auto &EventToStoreIn = MGraph.expired() ? MDefaultGraphDeps.LastEventPtr
505504
: MExtGraphDeps.LastEventPtr;
506505
EventToStoreIn = EventImpl;

sycl/source/detail/queue_impl.hpp

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -732,24 +732,14 @@ class queue_impl {
732732
finalizeHandlerInOrderNoEventsUnlocked(HandlerType &Handler) {
733733
assert(isInOrder());
734734
assert(MGraph.expired());
735-
assert(MDefaultGraphDeps.LastEventPtr == nullptr ||
736-
MContext->getBackend() == backend::opencl);
735+
assert(MDefaultGraphDeps.LastEventPtr == nullptr);
737736
assert(MNoEventMode);
738737

739738
MEmpty = false;
740739

741740
synchronizeWithExternalEvent(Handler);
742741

743-
if (MContext->getBackend() == backend::opencl && MGraph.expired()) {
744-
// This is needed to support queue_empty() call
745-
auto Event = parseEvent(Handler.finalize());
746-
if (Event) {
747-
MDefaultGraphDeps.LastEventPtr = Event;
748-
}
749-
return Event;
750-
} else {
751-
return parseEvent(Handler.finalize());
752-
}
742+
return parseEvent(Handler.finalize());
753743
}
754744

755745
template <typename HandlerType = handler>

sycl/test-e2e/InOrderEventsExt/get_last_event.cpp

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,10 @@ int Check(const sycl::queue &Q, const char *CheckName, const F &CheckFunc) {
3636
<< std::endl;
3737
return 1;
3838
}
39-
if (Q.get_backend() == sycl::backend::opencl) {
40-
if (*E != *LastEvent) {
41-
std::cout << "opencl backend should store last event in the queue"
42-
<< std::endl;
43-
return 1;
44-
}
45-
} else if (LastEvent->get_info<
46-
sycl::info::event::command_execution_status>() ==
47-
sycl::info::event_command_status::complete &&
48-
E->get_info<sycl::info::event::command_execution_status>() !=
49-
sycl::info::event_command_status::complete) {
39+
if (LastEvent->get_info<sycl::info::event::command_execution_status>() ==
40+
sycl::info::event_command_status::complete &&
41+
E->get_info<sycl::info::event::command_execution_status>() !=
42+
sycl::info::event_command_status::complete) {
5043
std::cout << "ext_oneapi_get_last_event() returned an event that is "
5144
"complete, but the event returned by CheckFunc() is not."
5245
<< std::endl;

sycl/test-e2e/InorderQueue/in_order_ext_oneapi_submit_barrier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ bool checkBarrierEvent(sycl::backend backend, sycl::event LastEvent,
1414
sycl::event BarrierEvent, bool noEventMode) {
1515
// In noEventMode or when using opencl backend,
1616
// barrier will always return last event
17-
if (backend == sycl::backend::opencl || !noEventMode) {
17+
if (!noEventMode) {
1818
return BarrierEvent == LastEvent;
1919
} else {
2020
return BarrierEvent != LastEvent;

sycl/unittests/scheduler/InOrderQueueHostTaskDeps.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,6 @@ TEST_F(SchedulerTest, InOrderQueueHostTaskDeps) {
4545
.wait();
4646

4747
size_t expectedCount = 1u;
48-
49-
// OpenCL needs to store all events so does not need a barrier
50-
if (Ctx.get_platform().get_backend() == backend::opencl)
51-
expectedCount = 0u;
52-
5348
EXPECT_EQ(GEventsWaitCounter, expectedCount);
5449
}
5550

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,20 @@ inline cl_event *ifUrEvent(ur_event_handle_t *ReturnedEvent, cl_event &Event) {
6969
inline ur_result_t createUREvent(cl_event Event, ur_context_handle_t Context,
7070
ur_queue_handle_t Queue,
7171
ur_event_handle_t *ReturnedEvent) {
72+
assert(Queue);
7273
if (ReturnedEvent) {
7374
try {
7475
auto UREvent =
7576
std::make_unique<ur_event_handle_t_>(Event, Context, Queue);
7677
*ReturnedEvent = UREvent.release();
78+
UR_RETURN_ON_FAILURE(Queue->storeLastEvent(*ReturnedEvent));
7779
} catch (std::bad_alloc &) {
7880
return UR_RESULT_ERROR_OUT_OF_RESOURCES;
7981
} catch (...) {
8082
return UR_RESULT_ERROR_UNKNOWN;
8183
}
84+
} else {
85+
UR_RETURN_ON_FAILURE(Queue->storeLastEvent(nullptr));
8286
}
8387
return UR_RESULT_SUCCESS;
8488
}

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

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ ur_result_t ur_queue_handle_t_::makeWithNative(native_type NativeQueue,
9494
UR_RETURN_ON_FAILURE(urDeviceCreateWithNativeHandle(
9595
hNativeHandle, nullptr, nullptr, &Device));
9696
}
97-
auto URQueue =
98-
std::make_unique<ur_queue_handle_t_>(NativeQueue, Context, Device);
97+
auto URQueue = std::make_unique<ur_queue_handle_t_>(NativeQueue, Context,
98+
Device, false);
9999
Queue = URQueue.release();
100100
} catch (std::bad_alloc &) {
101101
return UR_RESULT_ERROR_OUT_OF_RESOURCES;
@@ -125,14 +125,16 @@ UR_APIEXPORT ur_result_t UR_APICALL urQueueCreate(
125125

126126
cl_int RetErr = CL_INVALID_OPERATION;
127127

128+
bool InOrder = !(CLProperties & SupportByOpenCL &
129+
CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE);
128130
if (Version < oclv::V2_0) {
129131
cl_command_queue Queue =
130132
clCreateCommandQueue(hContext->CLContext, hDevice->CLDevice,
131133
CLProperties & SupportByOpenCL, &RetErr);
132134
CL_RETURN_ON_FAILURE(RetErr);
133135
try {
134-
auto URQueue =
135-
std::make_unique<ur_queue_handle_t_>(Queue, hContext, hDevice);
136+
auto URQueue = std::make_unique<ur_queue_handle_t_>(Queue, hContext,
137+
hDevice, InOrder);
136138
*phQueue = URQueue.release();
137139
} catch (std::bad_alloc &) {
138140
return UR_RESULT_ERROR_OUT_OF_RESOURCES;
@@ -151,7 +153,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urQueueCreate(
151153
CL_RETURN_ON_FAILURE(RetErr);
152154
try {
153155
auto URQueue =
154-
std::make_unique<ur_queue_handle_t_>(Queue, hContext, hDevice);
156+
std::make_unique<ur_queue_handle_t_>(Queue, hContext, hDevice, InOrder);
155157
*phQueue = URQueue.release();
156158
} catch (std::bad_alloc &) {
157159
return UR_RESULT_ERROR_OUT_OF_RESOURCES;
@@ -166,12 +168,23 @@ UR_APIEXPORT ur_result_t UR_APICALL urQueueGetInfo(ur_queue_handle_t hQueue,
166168
size_t propSize,
167169
void *pPropValue,
168170
size_t *pPropSizeRet) {
169-
if (propName == UR_QUEUE_INFO_EMPTY) {
170-
// OpenCL doesn't provide API to check the status of the queue.
171-
return UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION;
172-
}
173171
cl_command_queue_info CLCommandQueueInfo = mapURQueueInfoToCL(propName);
174172
UrReturnHelper ReturnValue(propSize, pPropValue, pPropSizeRet);
173+
if (propName == UR_QUEUE_INFO_EMPTY) {
174+
if (!hQueue->LastEvent) {
175+
// OpenCL doesn't provide API to check the status of the queue.
176+
return UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION;
177+
} else {
178+
ur_event_status_t Status;
179+
UR_RETURN_ON_FAILURE(urEventGetInfo(
180+
hQueue->LastEvent, UR_EVENT_INFO_COMMAND_EXECUTION_STATUS,
181+
sizeof(ur_event_status_t), (void *)&Status, nullptr));
182+
if (Status == UR_EVENT_STATUS_COMPLETE) {
183+
return ReturnValue(true);
184+
}
185+
return ReturnValue(false);
186+
}
187+
}
175188
switch (propName) {
176189
case UR_QUEUE_INFO_CONTEXT: {
177190
return ReturnValue(hQueue->Context);

unified-runtime/source/adapters/opencl/queue.hpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,14 @@ struct ur_queue_handle_t_ : ur::opencl::handle_base {
2424
std::optional<ur_queue_handle_t> DeviceDefault = std::nullopt;
2525
std::atomic<uint32_t> RefCount = 0;
2626
bool IsNativeHandleOwned = true;
27+
// Used to implement UR_QUEUE_INFO_EMPTY query
28+
bool IsInOrder;
29+
ur_event_handle_t LastEvent = nullptr;
2730

2831
ur_queue_handle_t_(native_type Queue, ur_context_handle_t Ctx,
29-
ur_device_handle_t Dev)
30-
: handle_base(), CLQueue(Queue), Context(Ctx), Device(Dev) {
32+
ur_device_handle_t Dev, bool InOrder)
33+
: handle_base(), CLQueue(Queue), Context(Ctx), Device(Dev),
34+
IsInOrder(InOrder) {
3135
RefCount = 1;
3236
urDeviceRetain(Device);
3337
urContextRetain(Context);
@@ -54,4 +58,20 @@ struct ur_queue_handle_t_ : ur::opencl::handle_base {
5458
uint32_t decrementReferenceCount() noexcept { return --RefCount; }
5559

5660
uint32_t getReferenceCount() const noexcept { return RefCount; }
61+
62+
// Stores last event for in-order queues. Has no effect if queue is Out Of
63+
// Order. The last event is used to implement UR_QUEUE_INFO_EMPTY query.
64+
ur_result_t storeLastEvent(ur_event_handle_t Event) {
65+
if (!IsInOrder) {
66+
return UR_RESULT_SUCCESS;
67+
}
68+
if (LastEvent) {
69+
UR_RETURN_ON_FAILURE(urEventRelease(LastEvent));
70+
}
71+
LastEvent = Event;
72+
if (LastEvent) {
73+
UR_RETURN_ON_FAILURE(urEventRetain(LastEvent));
74+
}
75+
return UR_RESULT_SUCCESS;
76+
}
5777
};

0 commit comments

Comments
 (0)