Skip to content

Commit 8c508fb

Browse files
committed
[SYCL][UR][OpenCL] Implement partial support for UR_QUEUE_INFO_EMPTY
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.
1 parent e7ab07d commit 8c508fb

File tree

8 files changed

+55
-42
lines changed

8 files changed

+55
-42
lines changed

sycl/source/detail/queue_impl.cpp

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

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

sycl/source/detail/queue_impl.hpp

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -722,24 +722,14 @@ class queue_impl {
722722
event finalizeHandlerInOrderNoEventsUnlocked(HandlerType &Handler) {
723723
assert(isInOrder());
724724
assert(MGraph.expired());
725-
assert(MDefaultGraphDeps.LastEventPtr == nullptr ||
726-
MContext->getBackend() == backend::opencl);
725+
assert(MDefaultGraphDeps.LastEventPtr == nullptr);
727726
assert(MNoEventMode);
728727

729728
MEmpty = false;
730729

731730
synchronizeWithExternalEvent(Handler);
732731

733-
if (MContext->getBackend() == backend::opencl && MGraph.expired()) {
734-
// This is needed to support queue_empty() call
735-
auto Event = Handler.finalize();
736-
if (!getSyclObjImpl(Event)->isDiscarded()) {
737-
MDefaultGraphDeps.LastEventPtr = getSyclObjImpl(Event);
738-
}
739-
return Event;
740-
} else {
741-
return Handler.finalize();
742-
}
732+
return Handler.finalize();
743733
}
744734

745735
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: 23 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,24 @@ 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+
} else {
185+
return ReturnValue(false);
186+
}
187+
}
188+
}
175189
switch (propName) {
176190
case UR_QUEUE_INFO_CONTEXT: {
177191
return ReturnValue(hQueue->Context);

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

Lines changed: 20 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,18 @@ 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+
ur_result_t storeLastEvent(ur_event_handle_t Event) {
63+
if (!IsInOrder) {
64+
return UR_RESULT_SUCCESS;
65+
}
66+
if (LastEvent) {
67+
UR_RETURN_ON_FAILURE(urEventRelease(LastEvent));
68+
}
69+
LastEvent = Event;
70+
if (LastEvent) {
71+
UR_RETURN_ON_FAILURE(urEventRetain(LastEvent));
72+
}
73+
return UR_RESULT_SUCCESS;
74+
}
5775
};

0 commit comments

Comments
 (0)