Skip to content

Commit a445325

Browse files
authored
[Offload] Don't create events for empty queues (#152304)
Add a device function to check if a device queue is empty. If liboffload tries to create an event for an empty queue, we create an "empty" event that is already complete. This allows `olCreateEvent`, `olSyncEvent` and `olWaitEvent` to run quickly for empty queues.
1 parent b9e133d commit a445325

File tree

6 files changed

+62
-4
lines changed

6 files changed

+62
-4
lines changed

offload/liboffload/src/OffloadImpl.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ struct ol_queue_impl_t {
7272
struct ol_event_impl_t {
7373
ol_event_impl_t(void *EventInfo, ol_queue_handle_t Queue)
7474
: EventInfo(EventInfo), Queue(Queue) {}
75+
// EventInfo may be null, in which case the event should be considered always
76+
// complete
7577
void *EventInfo;
7678
ol_queue_handle_t Queue;
7779
};
@@ -509,8 +511,8 @@ Error olWaitEvents_impl(ol_queue_handle_t Queue, ol_event_handle_t *Events,
509511
return Plugin::error(ErrorCode::INVALID_NULL_HANDLE,
510512
"olWaitEvents asked to wait on a NULL event");
511513

512-
// Do nothing if the event is for this queue
513-
if (Event->Queue == Queue)
514+
// Do nothing if the event is for this queue or the event is always complete
515+
if (Event->Queue == Queue || !Event->EventInfo)
514516
continue;
515517

516518
if (auto Err = Device->waitEvent(Event->EventInfo, Queue->AsyncInfo))
@@ -548,15 +550,20 @@ Error olGetQueueInfoSize_impl(ol_queue_handle_t Queue, ol_queue_info_t PropName,
548550
}
549551

550552
Error olSyncEvent_impl(ol_event_handle_t Event) {
553+
if (!Event->EventInfo)
554+
// Event always complete
555+
return Plugin::success();
556+
551557
if (auto Res = Event->Queue->Device->Device->syncEvent(Event->EventInfo))
552558
return Res;
553559

554560
return Error::success();
555561
}
556562

557563
Error olDestroyEvent_impl(ol_event_handle_t Event) {
558-
if (auto Res = Event->Queue->Device->Device->destroyEvent(Event->EventInfo))
559-
return Res;
564+
if (Event->EventInfo)
565+
if (auto Res = Event->Queue->Device->Device->destroyEvent(Event->EventInfo))
566+
return Res;
560567

561568
return olDestroy(Event);
562569
}
@@ -590,7 +597,16 @@ Error olGetEventInfoSize_impl(ol_event_handle_t Event, ol_event_info_t PropName,
590597
}
591598

592599
Error olCreateEvent_impl(ol_queue_handle_t Queue, ol_event_handle_t *EventOut) {
600+
auto Pending = Queue->Device->Device->hasPendingWork(Queue->AsyncInfo);
601+
if (auto Err = Pending.takeError())
602+
return Err;
603+
593604
*EventOut = new ol_event_impl_t(nullptr, Queue);
605+
if (!*Pending)
606+
// Queue is empty, don't record an event and consider the event always
607+
// complete
608+
return Plugin::success();
609+
594610
if (auto Res = Queue->Device->Device->createEvent(&(*EventOut)->EventInfo))
595611
return Res;
596612

offload/plugins-nextgen/amdgpu/src/rtl.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2591,6 +2591,17 @@ struct AMDGPUDeviceTy : public GenericDeviceTy, AMDGenericDeviceTy {
25912591
return Event->wait(*Stream);
25922592
}
25932593

2594+
Expected<bool> hasPendingWorkImpl(AsyncInfoWrapperTy &AsyncInfo) override {
2595+
auto Stream = AsyncInfo.getQueueAs<AMDGPUStreamTy *>();
2596+
if (!Stream)
2597+
return false;
2598+
2599+
auto Query = Stream->query();
2600+
if (Query)
2601+
return !*Query;
2602+
return Query.takeError();
2603+
}
2604+
25942605
/// Synchronize the current thread with the event.
25952606
Error syncEventImpl(void *EventPtr) override {
25962607
AMDGPUEventTy *Event = reinterpret_cast<AMDGPUEventTy *>(EventPtr);

offload/plugins-nextgen/common/include/PluginInterface.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,14 @@ struct GenericDeviceTy : public DeviceAllocatorTy {
973973
Error printInfo();
974974
virtual Expected<InfoTreeNode> obtainInfoImpl() = 0;
975975

976+
/// Return true if the device has work that is either queued or currently
977+
/// running
978+
///
979+
/// Devices which cannot report this information should always return true
980+
Expected<bool> hasPendingWork(__tgt_async_info *AsyncInfo);
981+
virtual Expected<bool>
982+
hasPendingWorkImpl(AsyncInfoWrapperTy &AsyncInfoWrapper) = 0;
983+
976984
/// Getters of the grid values.
977985
uint32_t getWarpSize() const { return GridValues.GV_Warp_Size; }
978986
uint32_t getThreadLimit() const { return GridValues.GV_Max_WG_Size; }

offload/plugins-nextgen/common/src/PluginInterface.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1626,6 +1626,21 @@ Error GenericDeviceTy::waitEvent(void *EventPtr, __tgt_async_info *AsyncInfo) {
16261626
return Err;
16271627
}
16281628

1629+
Expected<bool> GenericDeviceTy::hasPendingWork(__tgt_async_info *AsyncInfo) {
1630+
AsyncInfoWrapperTy AsyncInfoWrapper(*this, AsyncInfo);
1631+
auto Res = hasPendingWorkImpl(AsyncInfoWrapper);
1632+
if (auto Err = Res.takeError()) {
1633+
AsyncInfoWrapper.finalize(Err);
1634+
return Err;
1635+
}
1636+
1637+
auto Err = Plugin::success();
1638+
AsyncInfoWrapper.finalize(Err);
1639+
if (Err)
1640+
return Err;
1641+
return Res;
1642+
}
1643+
16291644
Error GenericDeviceTy::syncEvent(void *EventPtr) {
16301645
return syncEventImpl(EventPtr);
16311646
}

offload/plugins-nextgen/cuda/src/rtl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,11 @@ struct CUDADeviceTy : public GenericDeviceTy {
916916
return Plugin::check(Res, "error in cuStreamWaitEvent: %s");
917917
}
918918

919+
// TODO: This should be implementable on CUDA
920+
Expected<bool> hasPendingWorkImpl(AsyncInfoWrapperTy &AsyncInfo) override {
921+
return true;
922+
}
923+
919924
/// Synchronize the current thread with the event.
920925
Error syncEventImpl(void *EventPtr) override {
921926
CUevent Event = reinterpret_cast<CUevent>(EventPtr);

offload/plugins-nextgen/host/src/rtl.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,9 @@ struct GenELF64DeviceTy : public GenericDeviceTy {
333333
AsyncInfoWrapperTy &AsyncInfoWrapper) override {
334334
return Plugin::success();
335335
}
336+
Expected<bool> hasPendingWorkImpl(AsyncInfoWrapperTy &AsyncInfo) override {
337+
return true;
338+
}
336339
Error syncEventImpl(void *EventPtr) override { return Plugin::success(); }
337340

338341
/// Print information about the device.

0 commit comments

Comments
 (0)