diff --git a/sycl/source/detail/queue_impl.cpp b/sycl/source/detail/queue_impl.cpp index ccaab363c64b5..da07df6b949db 100644 --- a/sycl/source/detail/queue_impl.cpp +++ b/sycl/source/detail/queue_impl.cpp @@ -49,7 +49,7 @@ event queue_impl::memset(shared_ptr_class Impl, void *Ptr, return event(); event ResEvent{pi::cast(Event), Context}; - addEvent(ResEvent); + addUSMEvent(ResEvent); return ResEvent; } @@ -63,7 +63,7 @@ event queue_impl::memcpy(shared_ptr_class Impl, void *Dest, return event(); event ResEvent{pi::cast(Event), Context}; - addEvent(ResEvent); + addUSMEvent(ResEvent); return ResEvent; } @@ -81,13 +81,19 @@ event queue_impl::mem_advise(const void *Ptr, size_t Length, Advice, &Event); event ResEvent{pi::cast(Event), Context}; - addEvent(ResEvent); + addUSMEvent(ResEvent); return ResEvent; } void queue_impl::addEvent(event Event) { + std::weak_ptr EventWeakPtr{getSyclObjImpl(Event)}; std::lock_guard Guard(MMutex); - MEvents.push_back(std::move(Event)); + MEvents.push_back(std::move(EventWeakPtr)); +} + +void queue_impl::addUSMEvent(event Event) { + std::lock_guard Guard(MMutex); + MUSMEvents.push_back(std::move(Event)); } void *queue_impl::instrumentationProlog(const detail::code_location &CodeLoc, @@ -175,8 +181,13 @@ void queue_impl::wait(const detail::code_location &CodeLoc) { #endif std::lock_guard Guard(MMutex); - for (auto &Event : MEvents) + for (std::weak_ptr &EventImplWeakPtr : MEvents) { + if (std::shared_ptr EventImplPtr = EventImplWeakPtr.lock()) + EventImplPtr->wait(EventImplPtr); + } + for (event &Event : MUSMEvents) { Event.wait(); + } MEvents.clear(); #ifdef XPTI_ENABLE_INSTRUMENTATION diff --git a/sycl/source/detail/queue_impl.hpp b/sycl/source/detail/queue_impl.hpp index e48d59694af27..937223f114c5f 100644 --- a/sycl/source/detail/queue_impl.hpp +++ b/sycl/source/detail/queue_impl.hpp @@ -382,12 +382,20 @@ class queue_impl { /// \param Event is the event to be stored void addEvent(event Event); + /// Stores a USM operation event that should be associated with the queue + /// + /// \param Event is the event to be stored + void addUSMEvent(event Event); + /// Protects all the fields that can be changed by class' methods. mutex_class MMutex; DeviceImplPtr MDevice; const ContextImplPtr MContext; - vector_class MEvents; + vector_class> MEvents; + // USM operations are not added to the scheduler command graph, + // queue is the only owner on the runtime side. + vector_class MUSMEvents; exception_list MExceptions; const async_handler MAsyncHandler; const property_list MPropList; diff --git a/sycl/test/basic_tests/event_release.cpp b/sycl/test/basic_tests/event_release.cpp new file mode 100644 index 0000000000000..37e0d4258b28b --- /dev/null +++ b/sycl/test/basic_tests/event_release.cpp @@ -0,0 +1,38 @@ +// RUN: %clangxx -fsycl %s -o %t.out +// RUN: env SYCL_PI_TRACE=1 %CPU_RUN_PLACEHOLDER %t.out 2>&1 %CPU_CHECK_PLACEHOLDER +#include +#include +#include + +// The test checks that pi_events are released without queue destruction +// or call to queue::wait, when the corresponding commands are cleaned up. + +using namespace cl::sycl; + +class Foo; + +int main() { + int Val = 0; + int Gold = 42; + + queue Q; + + { + buffer Buf{&Val, range<1>(1)}; + Q.submit([&](handler &Cgh) { + auto Acc = Buf.get_access(Cgh); + Cgh.single_task([=]() { + Acc[0] = Gold; + }); + }); + } + + // Buffer destruction triggers execution graph cleanup, check that both + // events (one for launching the kernel and one for memory transfer to host) + // are released. + // CHECK: piEventRelease + // CHECK: piEventRelease + assert(Val == Gold); + // CHECK: End of main scope + std::cout << "End of main scope" << std::endl; +}