Skip to content

Commit bddc0a4

Browse files
[SYCL] WA for stream events cross dependency elimination (intel#14797)
Current stream implementation has a problem with cross dependency for inorder queue case. Both stream commands: kernel which writes and host task which prints are submitted to the same queue now, inorder queue mechanism of synchronization will add explicit dependency on kernel to the host task (this approach helps up to provide synchronization for kernel vs host tasks since no native sync is supported). Although kernel will add flush host task to its post-complete events storage to be able to wait for its completion in its own wait. This brings cross dependency that prevents event release. Current WA stores host task using weak reference that works in the same way but prevents cross dependency. Host task doesn't support (and not planned to support) post enqueue cleanup that means that its Command instance could be deleted only after host task completion and later. That means that absence of object in stored weak pointer is a solid sign of host task completion and we have no need to wait on it. If it is present we will try to wait on it if it is requested. This should be a temporal solution. Solution to be implemented later is elimination of forward references for stream and implementing a kind of aggregated events. --------- Signed-off-by: Tikhomirova, Kseniya <[email protected]> Co-authored-by: Sergey Semenov <[email protected]>
1 parent 367e948 commit bddc0a4

File tree

4 files changed

+23
-2
lines changed

4 files changed

+23
-2
lines changed

sycl/source/detail/event_impl.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ void event_impl::waitInternal(bool *Success) {
8181
// Wait for connected events(e.g. streams prints)
8282
for (const EventImplPtr &Event : MPostCompleteEvents)
8383
Event->wait(Event);
84+
for (const std::weak_ptr<event_impl> &WeakEventPtr :
85+
MWeakPostCompleteEvents) {
86+
if (EventImplPtr Event = WeakEventPtr.lock())
87+
Event->wait(Event);
88+
}
8489
}
8590

8691
void event_impl::setComplete() {

sycl/source/detail/event_impl.hpp

+15
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,11 @@ class event_impl {
270270
MPostCompleteEvents.push_back(Event);
271271
}
272272

273+
void attachEventToCompleteWeak(const std::weak_ptr<event_impl> &Event) {
274+
std::lock_guard<std::mutex> Lock(MMutex);
275+
MWeakPostCompleteEvents.push_back(Event);
276+
}
277+
273278
bool isDefaultConstructed() const noexcept { return MIsDefaultConstructed; }
274279

275280
ContextImplPtr getContextImplPtr() {
@@ -358,6 +363,16 @@ class event_impl {
358363
std::vector<EventImplPtr> MPreparedHostDepsEvents;
359364

360365
std::vector<EventImplPtr> MPostCompleteEvents;
366+
// short term WA for stream:
367+
// MPostCompleteEvents is split into two storages now. Original storage is
368+
// used by graph extension and represents backward links.
369+
// MWeakPostCompleteEvents represents weak forward references (used in stream
370+
// only). Used only for host tasks now since they do not support post enqueue
371+
// cleanup and event == nullptr could happen only when host task is completed
372+
// (and Command that holding reference to its event is deleted). TO DO: to
373+
// eliminate forward references from stream implementation and remove this
374+
// storage.
375+
std::vector<std::weak_ptr<event_impl>> MWeakPostCompleteEvents;
361376

362377
/// Indicates that the task associated with this event has been submitted by
363378
/// the queue to the device.

sycl/source/detail/queue_impl.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ event queue_impl::submit_impl(const std::function<void(handler &)> &CGF,
396396
event FlushEvent = submit_impl(
397397
[&](handler &ServiceCGH) { Stream->generateFlushCommand(ServiceCGH); },
398398
Self, PrimaryQueue, SecondaryQueue, /*CallerNeedsEvent*/ true, Loc, {});
399-
EventImpl->attachEventToComplete(detail::getSyclObjImpl(FlushEvent));
399+
EventImpl->attachEventToCompleteWeak(detail::getSyclObjImpl(FlushEvent));
400400
registerStreamServiceEvent(detail::getSyclObjImpl(FlushEvent));
401401
}
402402

sycl/unittests/scheduler/CommandsWaitForEvents.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ class EventImplProxyT : public sycl::detail::event_impl {
130130
public:
131131
using sycl::detail::event_impl::MPostCompleteEvents;
132132
using sycl::detail::event_impl::MState;
133+
using sycl::detail::event_impl::MWeakPostCompleteEvents;
133134
};
134135

135136
class QueueImplProxyT : public sycl::detail::queue_impl {
@@ -165,7 +166,7 @@ TEST_F(SchedulerTest, StreamAUXCmdsWait) {
165166

166167
auto EventImplProxy = std::static_pointer_cast<EventImplProxyT>(EventImpl);
167168

168-
ASSERT_EQ(EventImplProxy->MPostCompleteEvents.size(), 1u)
169+
ASSERT_EQ(EventImplProxy->MWeakPostCompleteEvents.size(), 1u)
169170
<< "Expected 1 post complete event";
170171

171172
Q.wait();

0 commit comments

Comments
 (0)