Skip to content

Commit

Permalink
[SYCL] Add more cleanup points close to the shutdown (intel#11119)
Browse files Browse the repository at this point in the history
Previously we tried to release internal resources only when the last
(likely main) thread exits. For multi threaded applications it could be
not functional. e.g. threads are closed during module unload and when
main thread exits - other threads are still alive. Adding logic to try
non blocking release for every thread exit and blocking for the last
one.

---------

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova@intel.com>
  • Loading branch information
KseniyaTikhomirova authored Oct 27, 2023
1 parent ec54804 commit 4156f78
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 16 deletions.
22 changes: 11 additions & 11 deletions sycl/source/detail/global_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,11 @@ class ObjectUsageCounter {
if (!MModifyCounter)
return;

LockGuard Guard(GlobalHandler::MSyclGlobalHandlerProtector);
MCounter--;
if (!MCounter) {
LockGuard Guard(GlobalHandler::MSyclGlobalHandlerProtector);
GlobalHandler *RTGlobalObjHandler = GlobalHandler::getInstancePtr();
if (RTGlobalObjHandler) {
RTGlobalObjHandler->prepareSchedulerToRelease();
}
GlobalHandler *RTGlobalObjHandler = GlobalHandler::getInstancePtr();
if (RTGlobalObjHandler) {
RTGlobalObjHandler->prepareSchedulerToRelease(!MCounter);
}
}

Expand Down Expand Up @@ -142,7 +140,7 @@ void GlobalHandler::attachScheduler(Scheduler *Scheduler) {
// The method is used in unit tests only. Do not protect with lock since
// releaseResources will cause dead lock due to host queue release
if (MScheduler.Inst)
prepareSchedulerToRelease();
prepareSchedulerToRelease(true);
MScheduler.Inst.reset(Scheduler);
}

Expand Down Expand Up @@ -273,11 +271,13 @@ void GlobalHandler::unloadPlugins() {
getPlugins().clear();
}

void GlobalHandler::prepareSchedulerToRelease() {
void GlobalHandler::prepareSchedulerToRelease(bool Blocking) {
#ifndef _WIN32
drainThreadPool();
if (Blocking)
drainThreadPool();
if (MScheduler.Inst)
MScheduler.Inst->releaseResources();
MScheduler.Inst->releaseResources(Blocking ? BlockingT::BLOCKING
: BlockingT::NON_BLOCKING);
#endif
}

Expand Down Expand Up @@ -306,7 +306,7 @@ void shutdown() {

// Ensure neither host task is working so that no default context is accessed
// upon its release
Handler->prepareSchedulerToRelease();
Handler->prepareSchedulerToRelease(true);

if (Handler->MHostTaskThreadPool.Inst)
Handler->MHostTaskThreadPool.Inst->finishAndWait();
Expand Down
2 changes: 1 addition & 1 deletion sycl/source/detail/global_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class GlobalHandler {
void unloadPlugins();
void releaseDefaultContexts();
void drainThreadPool();
void prepareSchedulerToRelease();
void prepareSchedulerToRelease(bool Blocking);

void InitXPTI();
void TraceEventXPTI(const char *Message);
Expand Down
6 changes: 3 additions & 3 deletions sycl/source/detail/scheduler/scheduler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -405,13 +405,13 @@ Scheduler::Scheduler() {

Scheduler::~Scheduler() { DefaultHostQueue.reset(); }

void Scheduler::releaseResources() {
void Scheduler::releaseResources(BlockingT Blocking) {
// There might be some commands scheduled for post enqueue cleanup that
// haven't been freed because of the graph mutex being locked at the time,
// clean them up now.
cleanupCommands({});

cleanupAuxiliaryResources(BlockingT::BLOCKING);
cleanupAuxiliaryResources(Blocking);
// We need loop since sometimes we may need new objects to be added to
// deferred mem objects storage during cleanup. Known example is: we cleanup
// existing deferred mem objects under write lock, during this process we
Expand All @@ -420,7 +420,7 @@ void Scheduler::releaseResources() {
// with size only so all confitions for deferred release are satisfied) is
// added to deferred mem obj storage. So we may end up with leak.
while (!isDeferredMemObjectsEmpty())
cleanupDeferredMemObjects(BlockingT::BLOCKING);
cleanupDeferredMemObjects(Blocking);
}

MemObjRecord *Scheduler::getMemObjRecord(const Requirement *const Req) {
Expand Down
2 changes: 1 addition & 1 deletion sycl/source/detail/scheduler/scheduler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ class Scheduler {

Scheduler();
~Scheduler();
void releaseResources();
void releaseResources(BlockingT Blocking = BlockingT::BLOCKING);
bool isDeferredMemObjectsEmpty();

void enqueueCommandForCG(EventImplPtr NewEvent,
Expand Down

0 comments on commit 4156f78

Please sign in to comment.