From 55b417a75fb4cbd13066510cba13d1c214095eab Mon Sep 17 00:00:00 2001 From: Ross Brunton Date: Wed, 16 Jul 2025 18:32:47 +0100 Subject: [Offload] Cache symbols in program (#148209) When creating a new symbol, check that it already exists. If it does, return that pointer rather than building a new symbol structure. --- offload/liboffload/src/OffloadImpl.cpp | 57 ++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 23 deletions(-) (limited to 'offload/liboffload/src/OffloadImpl.cpp') diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp index c4e7f9689a90..ffc9016bca0a 100644 --- a/offload/liboffload/src/OffloadImpl.cpp +++ b/offload/liboffload/src/OffloadImpl.cpp @@ -84,17 +84,20 @@ struct ol_program_impl_t { DeviceImage(DeviceImage) {} plugin::DeviceImageTy *Image; std::unique_ptr ImageData; - std::vector> Symbols; + std::mutex SymbolListMutex; __tgt_device_image DeviceImage; + llvm::StringMap> KernelSymbols; + llvm::StringMap> GlobalSymbols; }; struct ol_symbol_impl_t { - ol_symbol_impl_t(GenericKernelTy *Kernel) - : PluginImpl(Kernel), Kind(OL_SYMBOL_KIND_KERNEL) {} - ol_symbol_impl_t(GlobalTy &&Global) - : PluginImpl(Global), Kind(OL_SYMBOL_KIND_GLOBAL_VARIABLE) {} + ol_symbol_impl_t(const char *Name, GenericKernelTy *Kernel) + : PluginImpl(Kernel), Kind(OL_SYMBOL_KIND_KERNEL), Name(Name) {} + ol_symbol_impl_t(const char *Name, GlobalTy &&Global) + : PluginImpl(Global), Kind(OL_SYMBOL_KIND_GLOBAL_VARIABLE), Name(Name) {} std::variant PluginImpl; ol_symbol_kind_t Kind; + llvm::StringRef Name; }; namespace llvm { @@ -714,32 +717,40 @@ Error olGetSymbol_impl(ol_program_handle_t Program, const char *Name, ol_symbol_kind_t Kind, ol_symbol_handle_t *Symbol) { auto &Device = Program->Image->getDevice(); + std::lock_guard Lock{Program->SymbolListMutex}; + switch (Kind) { case OL_SYMBOL_KIND_KERNEL: { - auto KernelImpl = Device.constructKernel(Name); - if (!KernelImpl) - return KernelImpl.takeError(); + auto &Kernel = Program->KernelSymbols[Name]; + if (!Kernel) { + auto KernelImpl = Device.constructKernel(Name); + if (!KernelImpl) + return KernelImpl.takeError(); - if (auto Err = KernelImpl->init(Device, *Program->Image)) - return Err; + if (auto Err = KernelImpl->init(Device, *Program->Image)) + return Err; + + Kernel = std::make_unique(KernelImpl->getName(), + &*KernelImpl); + } - *Symbol = - Program->Symbols - .emplace_back(std::make_unique(&*KernelImpl)) - .get(); + *Symbol = Kernel.get(); return Error::success(); } case OL_SYMBOL_KIND_GLOBAL_VARIABLE: { - GlobalTy GlobalObj{Name}; - if (auto Res = Device.Plugin.getGlobalHandler().getGlobalMetadataFromDevice( - Device, *Program->Image, GlobalObj)) - return Res; - - *Symbol = Program->Symbols - .emplace_back( - std::make_unique(std::move(GlobalObj))) - .get(); + auto &Global = Program->KernelSymbols[Name]; + if (!Global) { + GlobalTy GlobalObj{Name}; + if (auto Res = + Device.Plugin.getGlobalHandler().getGlobalMetadataFromDevice( + Device, *Program->Image, GlobalObj)) + return Res; + + Global = std::make_unique(GlobalObj.getName().c_str(), + std::move(GlobalObj)); + } + *Symbol = Global.get(); return Error::success(); } default: -- cgit v1.2.3 From 2726b7fb1c0768bf404a712e5940b64db9fed5e1 Mon Sep 17 00:00:00 2001 From: Ross Brunton Date: Wed, 23 Jul 2025 10:52:13 +0100 Subject: [Offload] Rename olWaitEvent/Queue to olSyncEvent/Queue (#150023) This more closely matches the nomenclature used by CUDA, AMDGPU and the plugin interface. --- offload/liboffload/src/OffloadImpl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'offload/liboffload/src/OffloadImpl.cpp') diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp index ffc9016bca0a..d93e4f1db58a 100644 --- a/offload/liboffload/src/OffloadImpl.cpp +++ b/offload/liboffload/src/OffloadImpl.cpp @@ -483,7 +483,7 @@ Error olCreateQueue_impl(ol_device_handle_t Device, ol_queue_handle_t *Queue) { Error olDestroyQueue_impl(ol_queue_handle_t Queue) { return olDestroy(Queue); } -Error olWaitQueue_impl(ol_queue_handle_t Queue) { +Error olSyncQueue_impl(ol_queue_handle_t Queue) { // Host plugin doesn't have a queue set so it's not safe to call synchronize // on it, but we have nothing to synchronize in that situation anyway. if (Queue->AsyncInfo->Queue) { @@ -527,7 +527,7 @@ Error olGetQueueInfoSize_impl(ol_queue_handle_t Queue, ol_queue_info_t PropName, return olGetQueueInfoImplDetail(Queue, PropName, 0, nullptr, PropSizeRet); } -Error olWaitEvent_impl(ol_event_handle_t Event) { +Error olSyncEvent_impl(ol_event_handle_t Event) { if (auto Res = Event->Queue->Device->Device->syncEvent(Event->EventInfo)) return Res; -- cgit v1.2.3 From 081b74caf5fbfe04abc372c453cb1d6fc8f781a7 Mon Sep 17 00:00:00 2001 From: Ross Brunton Date: Wed, 23 Jul 2025 14:12:16 +0100 Subject: [Offload] Add olWaitEvents (#150036) This function causes a queue to wait until all the provided events have completed before running any future scheduled work. --- offload/liboffload/src/OffloadImpl.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'offload/liboffload/src/OffloadImpl.cpp') diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp index d93e4f1db58a..87f924168272 100644 --- a/offload/liboffload/src/OffloadImpl.cpp +++ b/offload/liboffload/src/OffloadImpl.cpp @@ -500,6 +500,28 @@ Error olSyncQueue_impl(ol_queue_handle_t Queue) { return Error::success(); } +Error olWaitEvents_impl(ol_queue_handle_t Queue, ol_event_handle_t *Events, + size_t NumEvents) { + auto *Device = Queue->Device->Device; + + for (size_t I = 0; I < NumEvents; I++) { + auto *Event = Events[I]; + + if (!Event) + return Plugin::error(ErrorCode::INVALID_NULL_HANDLE, + "olWaitEvents asked to wait on a NULL event"); + + // Do nothing if the event is for this queue + if (Event->Queue == Queue) + continue; + + if (auto Err = Device->waitEvent(Event->EventInfo, Queue->AsyncInfo)) + return Err; + } + + return Error::success(); +} + Error olGetQueueInfoImplDetail(ol_queue_handle_t Queue, ol_queue_info_t PropName, size_t PropSize, void *PropValue, size_t *PropSizeRet) { -- cgit v1.2.3 From 690c3ee5be51bf0b6598b1a202ceb7dec6acebbd Mon Sep 17 00:00:00 2001 From: Ross Brunton Date: Thu, 24 Jul 2025 14:31:06 +0100 Subject: [Offload] Replace "EventOut" parameters with `olCreateEvent` (#150217) Rather than having every "enqueue"-type function have an output pointer specifically for an output event, just provide an `olCreateEvent` entrypoint which pushes an event to the queue. For example, replace: ```cpp olMemcpy(Queue, ..., EventOut); ``` with ```cpp olMemcpy(Queue, ...); olCreateEvent(Queue, EventOut); ``` --- offload/liboffload/src/OffloadImpl.cpp | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) (limited to 'offload/liboffload/src/OffloadImpl.cpp') diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp index 87f924168272..8f316b87fc47 100644 --- a/offload/liboffload/src/OffloadImpl.cpp +++ b/offload/liboffload/src/OffloadImpl.cpp @@ -591,26 +591,21 @@ Error olGetEventInfoSize_impl(ol_event_handle_t Event, ol_event_info_t PropName, return olGetEventInfoImplDetail(Event, PropName, 0, nullptr, PropSizeRet); } -ol_event_handle_t makeEvent(ol_queue_handle_t Queue) { - auto EventImpl = std::make_unique(nullptr, Queue); - if (auto Res = Queue->Device->Device->createEvent(&EventImpl->EventInfo)) { - llvm::consumeError(std::move(Res)); - return nullptr; - } +Error olCreateEvent_impl(ol_queue_handle_t Queue, ol_event_handle_t *EventOut) { + *EventOut = new ol_event_impl_t(nullptr, Queue); + if (auto Res = Queue->Device->Device->createEvent(&(*EventOut)->EventInfo)) + return Res; - if (auto Res = Queue->Device->Device->recordEvent(EventImpl->EventInfo, - Queue->AsyncInfo)) { - llvm::consumeError(std::move(Res)); - return nullptr; - } + if (auto Res = Queue->Device->Device->recordEvent((*EventOut)->EventInfo, + Queue->AsyncInfo)) + return Res; - return EventImpl.release(); + return Plugin::success(); } Error olMemcpy_impl(ol_queue_handle_t Queue, void *DstPtr, ol_device_handle_t DstDevice, const void *SrcPtr, - ol_device_handle_t SrcDevice, size_t Size, - ol_event_handle_t *EventOut) { + ol_device_handle_t SrcDevice, size_t Size) { auto Host = OffloadContext::get().HostDevice(); if (DstDevice == Host && SrcDevice == Host) { if (!Queue) { @@ -641,9 +636,6 @@ Error olMemcpy_impl(ol_queue_handle_t Queue, void *DstPtr, return Res; } - if (EventOut) - *EventOut = makeEvent(Queue); - return Error::success(); } @@ -690,8 +682,7 @@ Error olDestroyProgram_impl(ol_program_handle_t Program) { Error olLaunchKernel_impl(ol_queue_handle_t Queue, ol_device_handle_t Device, ol_symbol_handle_t Kernel, const void *ArgumentsData, size_t ArgumentsSize, - const ol_kernel_launch_size_args_t *LaunchSizeArgs, - ol_event_handle_t *EventOut) { + const ol_kernel_launch_size_args_t *LaunchSizeArgs) { auto *DeviceImpl = Device->Device; if (Queue && Device != Queue->Device) { return createOffloadError( @@ -729,9 +720,6 @@ Error olLaunchKernel_impl(ol_queue_handle_t Queue, ol_device_handle_t Device, if (Err) return Err; - if (EventOut) - *EventOut = makeEvent(Queue); - return Error::success(); } -- cgit v1.2.3