From b0fc609ff1de7d829da6ecfe00f7c7620c1a2fb8 Mon Sep 17 00:00:00 2001 From: Vladimir Lazarev Date: Wed, 23 Sep 2020 16:25:10 +0300 Subject: [PATCH 1/3] [SYCL] Avoid overuse of CPU on wait mutex loop The while loop in lockSharedTimedMutex causes 100% usage of CPU if host apptication generates command groups in multiple threads That slow downs overall execution. Unify code of cleanupFinishedCommands fucntion with rest of module. Dead-lock is avoided by use of non-blocking lock operations. --- sycl/source/detail/scheduler/scheduler.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sycl/source/detail/scheduler/scheduler.cpp b/sycl/source/detail/scheduler/scheduler.cpp index 1ca92d93080c4..c1eeecebbd2c5 100644 --- a/sycl/source/detail/scheduler/scheduler.cpp +++ b/sycl/source/detail/scheduler/scheduler.cpp @@ -12,9 +12,11 @@ #include #include +#include #include #include #include +#include #include __SYCL_INLINE_NAMESPACE(cl) { @@ -153,11 +155,9 @@ void Scheduler::waitForEvent(EventImplPtr Event) { } void Scheduler::cleanupFinishedCommands(EventImplPtr FinishedEvent) { - // Avoiding deadlock situation, where one thread is in the process of - // enqueueing (with a locked mutex) a currently blocked task that waits for - // another thread which is stuck at attempting cleanup. - std::unique_lock Lock(MGraphLock, std::try_to_lock); - if (Lock.owns_lock()) { + std::unique_lock Lock(MGraphLock, std::defer_lock); + { + lockSharedTimedMutex(Lock); Command *FinishedCmd = static_cast(FinishedEvent->getCommand()); // The command might have been cleaned up (and set to nullptr) by another // thread @@ -268,7 +268,8 @@ void Scheduler::lockSharedTimedMutex( // TODO: after switching to C++17, change std::shared_timed_mutex to // std::shared_mutex and use std::lock_guard here both for Windows and Linux. while (!Lock.owns_lock()) { - Lock.try_lock(); + Lock.try_lock_for(std::chrono::milliseconds(10)); + std::this_thread::yield(); } #else // It is a deadlock on UNIX in implementation of lock and lock_shared, if From fa932e7e547bbff064a52978b475355ef9d749fb Mon Sep 17 00:00:00 2001 From: Vladimir Lazarev Date: Wed, 23 Sep 2020 20:07:43 +0300 Subject: [PATCH 2/3] [SYCL] revert unnecessary change --- sycl/source/detail/scheduler/scheduler.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sycl/source/detail/scheduler/scheduler.cpp b/sycl/source/detail/scheduler/scheduler.cpp index c1eeecebbd2c5..31beedf96b110 100644 --- a/sycl/source/detail/scheduler/scheduler.cpp +++ b/sycl/source/detail/scheduler/scheduler.cpp @@ -155,9 +155,11 @@ void Scheduler::waitForEvent(EventImplPtr Event) { } void Scheduler::cleanupFinishedCommands(EventImplPtr FinishedEvent) { - std::unique_lock Lock(MGraphLock, std::defer_lock); - { - lockSharedTimedMutex(Lock); + // Avoiding deadlock situation, where one thread is in the process of + // enqueueing (with a locked mutex) a currently blocked task that waits for + // another thread which is stuck at attempting cleanup. + std::unique_lock Lock(MGraphLock, std::try_to_lock); + if (Lock.owns_lock()) { Command *FinishedCmd = static_cast(FinishedEvent->getCommand()); // The command might have been cleaned up (and set to nullptr) by another // thread From e13fd3cd9c96a6b3f5502bc5e2e461839cd562b9 Mon Sep 17 00:00:00 2001 From: Vladimir Lazarev Date: Thu, 24 Sep 2020 08:42:50 +0300 Subject: [PATCH 3/3] [SYCL] add comment describing change --- sycl/source/detail/scheduler/scheduler.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sycl/source/detail/scheduler/scheduler.cpp b/sycl/source/detail/scheduler/scheduler.cpp index 31beedf96b110..8c67225b7b98b 100644 --- a/sycl/source/detail/scheduler/scheduler.cpp +++ b/sycl/source/detail/scheduler/scheduler.cpp @@ -271,6 +271,9 @@ void Scheduler::lockSharedTimedMutex( // std::shared_mutex and use std::lock_guard here both for Windows and Linux. while (!Lock.owns_lock()) { Lock.try_lock_for(std::chrono::milliseconds(10)); + // Without yield while loop acts like endless while loop and occupies the + // whole CPU when multiple command groups are created in multiple host + // threads std::this_thread::yield(); } #else