Skip to content

Commit 5bb3ab9

Browse files
authored
[SYCL] Clear event_impl dependencies with graph cleanup (#4793)
When event_impl's d-tor is called its dependencies are starting to recursive releasing. It leads to stack overflow. Clearing event_impl dependencies in graph cleanup helps to eliminate this problem. getWaitList was moved to event_impl class so the work with dependencies could be wrapped to mutex. Test : intel/llvm-test-suite#574 Signed-off-by: mdimakov <[email protected]>
1 parent b5b6673 commit 5bb3ab9

File tree

7 files changed

+51
-37
lines changed

7 files changed

+51
-37
lines changed

sycl/source/detail/event_impl.cpp

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -210,18 +210,24 @@ void event_impl::wait(
210210

211211
void event_impl::wait_and_throw(
212212
std::shared_ptr<cl::sycl::detail::event_impl> Self) {
213-
Command *Cmd = static_cast<Command *>(Self->getCommand());
214-
QueueImplPtr submittedQueue = nullptr;
215-
if (Cmd)
216-
submittedQueue = Cmd->getSubmittedQueue();
213+
Scheduler &Sched = Scheduler::getInstance();
217214

215+
QueueImplPtr submittedQueue = nullptr;
216+
{
217+
Scheduler::ReadLockT Lock(Sched.MGraphLock);
218+
Command *Cmd = static_cast<Command *>(Self->getCommand());
219+
if (Cmd)
220+
submittedQueue = Cmd->getSubmittedQueue();
221+
}
218222
wait(Self);
219223

220-
for (auto &EventImpl :
221-
detail::Scheduler::getInstance().getWaitList(std::move(Self))) {
222-
Command *Cmd = (Command *)EventImpl->getCommand();
223-
if (Cmd)
224-
Cmd->getSubmittedQueue()->throw_asynchronous();
224+
{
225+
Scheduler::ReadLockT Lock(Sched.MGraphLock);
226+
for (auto &EventImpl : getWaitList()) {
227+
Command *Cmd = (Command *)EventImpl->getCommand();
228+
if (Cmd)
229+
Cmd->getSubmittedQueue()->throw_asynchronous();
230+
}
225231
}
226232
if (submittedQueue)
227233
submittedQueue->throw_asynchronous();
@@ -325,6 +331,25 @@ pi_native_handle event_impl::getNative() const {
325331
return Handle;
326332
}
327333

334+
std::vector<EventImplPtr> event_impl::getWaitList() {
335+
std::lock_guard<std::mutex> Lock(MMutex);
336+
337+
std::vector<EventImplPtr> Result;
338+
Result.reserve(MPreparedDepsEvents.size() + MPreparedHostDepsEvents.size());
339+
Result.insert(Result.end(), MPreparedDepsEvents.begin(),
340+
MPreparedDepsEvents.end());
341+
Result.insert(Result.end(), MPreparedHostDepsEvents.begin(),
342+
MPreparedHostDepsEvents.end());
343+
344+
return Result;
345+
}
346+
347+
void event_impl::cleanupDependencyEvents() {
348+
std::lock_guard<std::mutex> Lock(MMutex);
349+
MPreparedDepsEvents.clear();
350+
MPreparedHostDepsEvents.clear();
351+
}
352+
328353
} // namespace detail
329354
} // namespace sycl
330355
} // __SYCL_INLINE_NAMESPACE(cl)

sycl/source/detail/event_impl.hpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class context_impl;
2727
using ContextImplPtr = std::shared_ptr<cl::sycl::detail::context_impl>;
2828
class queue_impl;
2929
using QueueImplPtr = std::shared_ptr<cl::sycl::detail::queue_impl>;
30+
class event_impl;
31+
using EventImplPtr = std::shared_ptr<cl::sycl::detail::event_impl>;
3032

3133
class event_impl {
3234
public:
@@ -175,6 +177,14 @@ class event_impl {
175177
return MPreparedHostDepsEvents;
176178
}
177179

180+
/// Returns vector of event_impl that this event_impl depends on.
181+
///
182+
/// @return a vector of "immediate" dependencies for this event_impl.
183+
std::vector<EventImplPtr> getWaitList();
184+
185+
/// Cleans dependencies of this event_impl
186+
void cleanupDependencyEvents();
187+
178188
private:
179189
// When instrumentation is enabled emits trace event for event wait begin and
180190
// returns the telemetry event generated for the wait
@@ -192,15 +202,17 @@ class event_impl {
192202
void *MCommand = nullptr;
193203

194204
/// Dependency events prepared for waiting by backend.
195-
std::vector<std::shared_ptr<event_impl>> MPreparedDepsEvents;
196-
std::vector<std::shared_ptr<event_impl>> MPreparedHostDepsEvents;
205+
std::vector<EventImplPtr> MPreparedDepsEvents;
206+
std::vector<EventImplPtr> MPreparedHostDepsEvents;
197207

198208
enum HostEventState : int { HES_NotComplete = 0, HES_Complete };
199209

200210
// State of host event. Employed only for host events and event with no
201211
// backend's representation (e.g. alloca). Used values are listed in
202212
// HostEventState enum.
203213
std::atomic<int> MState;
214+
215+
std::mutex MMutex;
204216
};
205217

206218
} // namespace detail

sycl/source/detail/scheduler/graph_builder.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ static void handleVisitedNodes(std::vector<Command *> &Visited) {
129129
for (Command *Cmd : Visited) {
130130
if (Cmd->MMarks.MToBeDeleted) {
131131
Cmd->getEvent()->setCommand(nullptr);
132+
Cmd->getEvent()->cleanupDependencyEvents();
132133
delete Cmd;
133134
} else
134135
Cmd->MMarks.MVisited = false;

sycl/source/detail/scheduler/graph_processor.cpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,6 @@ static Command *getCommand(const EventImplPtr &Event) {
2121
return (Command *)Event->getCommand();
2222
}
2323

24-
std::vector<EventImplPtr>
25-
Scheduler::GraphProcessor::getWaitList(EventImplPtr Event) {
26-
std::vector<EventImplPtr> Result;
27-
const std::vector<EventImplPtr> &PDeps = Event->getPreparedDepsEvents();
28-
const std::vector<EventImplPtr> &PHDeps = Event->getPreparedHostDepsEvents();
29-
30-
Result.reserve(PDeps.size() + PHDeps.size());
31-
Result.insert(Result.end(), PDeps.begin(), PDeps.end());
32-
Result.insert(Result.end(), PHDeps.begin(), PHDeps.end());
33-
34-
return Result;
35-
}
36-
3724
void Scheduler::GraphProcessor::waitForEvent(EventImplPtr Event,
3825
ReadLockT &GraphReadLock,
3926
bool LockTheLock) {

sycl/source/detail/scheduler/scheduler.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -206,11 +206,6 @@ Scheduler &Scheduler::getInstance() {
206206
return GlobalHandler::instance().getScheduler();
207207
}
208208

209-
std::vector<EventImplPtr> Scheduler::getWaitList(EventImplPtr Event) {
210-
ReadLockT Lock(MGraphLock);
211-
return GraphProcessor::getWaitList(std::move(Event));
212-
}
213-
214209
void Scheduler::waitForEvent(EventImplPtr Event) {
215210
ReadLockT Lock(MGraphLock);
216211
// It's fine to leave the lock unlocked upon return from waitForEvent as

sycl/source/detail/scheduler/scheduler.hpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -427,9 +427,6 @@ class Scheduler {
427427
/// \return an instance of the scheduler object.
428428
static Scheduler &getInstance();
429429

430-
/// \return a vector of "immediate" dependencies for the Event given.
431-
std::vector<EventImplPtr> getWaitList(EventImplPtr Event);
432-
433430
/// Allocate buffers in the pool for a provided stream
434431
///
435432
/// \param Impl to the stream object
@@ -721,10 +718,6 @@ class Scheduler {
721718
/// \ingroup sycl_graph
722719
class GraphProcessor {
723720
public:
724-
/// \return a list of events that represent immediate dependencies of the
725-
/// command associated with Event passed.
726-
static std::vector<EventImplPtr> getWaitList(EventImplPtr Event);
727-
728721
/// Waits for the command, associated with Event passed, is completed.
729722
/// \param GraphReadLock read-lock which is already acquired for reading
730723
/// \param LockTheLock selects if graph lock should be locked upon return
@@ -763,6 +756,7 @@ class Scheduler {
763756
friend class Command;
764757
friend class DispatchHostTask;
765758
friend class queue_impl;
759+
friend class event_impl;
766760

767761
/// Stream buffers structure.
768762
///

sycl/source/event.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ void event::wait_and_throw(const std::vector<event> &EventList) {
5555
std::vector<event> event::get_wait_list() {
5656
std::vector<event> Result;
5757

58-
for (auto &EventImpl : detail::Scheduler::getInstance().getWaitList(impl))
58+
for (auto &EventImpl : impl->getWaitList())
5959
Result.push_back(detail::createSyclObjFromImpl<event>(EventImpl));
6060

6161
return Result;

0 commit comments

Comments
 (0)