From c4e36bda61ec470f84b93308fbc77280cd4a5090 Mon Sep 17 00:00:00 2001 From: Sergey Kanaev Date: Fri, 9 Jul 2021 22:42:40 +0300 Subject: [PATCH 1/2] Report exceptions during wait for host-tasks dependencies Signed-off-by: Sergey Kanaev --- sycl/source/detail/scheduler/commands.cpp | 35 +++++++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/sycl/source/detail/scheduler/commands.cpp b/sycl/source/detail/scheduler/commands.cpp index e0f28f1b9c2de..139c68b68f95b 100644 --- a/sycl/source/detail/scheduler/commands.cpp +++ b/sycl/source/detail/scheduler/commands.cpp @@ -169,7 +169,7 @@ class DispatchHostTask { ExecCGCommand *MThisCmd; std::vector MReqToMem; - void waitForEvents() const { + pi_result waitForEvents() const { std::map> RequiredEventsPerPlugin; @@ -185,14 +185,27 @@ class DispatchHostTask { // other available job and resume once all required events are ready. for (auto &PluginWithEvents : RequiredEventsPerPlugin) { std::vector RawEvents = getPiEvents(PluginWithEvents.second); - PluginWithEvents.first->call(RawEvents.size(), - RawEvents.data()); + try { + PluginWithEvents.first->call(RawEvents.size(), + RawEvents.data()); + } catch (const sycl::exception &E) { + CGHostTask &HostTask = static_cast(MThisCmd->getCG()); + HostTask.MQueue->reportAsyncException(std::current_exception()); + return (pi_result)E.get_cl_code(); + } catch (...) { + CGHostTask &HostTask = static_cast(MThisCmd->getCG()); + HostTask.MQueue->reportAsyncException(std::current_exception()); + return PI_ERROR_UNKNOWN; + } } - // wait for dependency host events + // Wait for dependency host events. + // Host events can't throw exceptions so don't try to catch it. for (const EventImplPtr &Event : MThisCmd->MPreparedHostDepsEvents) { Event->waitInternal(); } + + return PI_SUCCESS; } public: @@ -201,12 +214,22 @@ class DispatchHostTask { : MThisCmd{ThisCmd}, MReqToMem(std::move(ReqToMem)) {} void operator()() const { - waitForEvents(); - assert(MThisCmd->getCG().getType() == CG::CGTYPE::CODEPLAY_HOST_TASK); CGHostTask &HostTask = static_cast(MThisCmd->getCG()); + pi_result WaitResult = waitForEvents(); + if (WaitResult != PI_SUCCESS) { + std::exception_ptr EPtr = std::make_exception_ptr(sycl::runtime_error( + std::string("Couldn't wait for host-task's dependencies"), + WaitResult)); + HostTask.MQueue->reportAsyncException(EPtr); + + // reset host-task's lambda and quit + HostTask.MHostTask.reset(); + return; + } + try { // we're ready to call the user-defined lambda now if (HostTask.MHostTask->isInteropTask()) { From d63eaa01c531e61a3773922237b5448f2e97e3be Mon Sep 17 00:00:00 2001 From: Sergey Kanaev Date: Wed, 14 Jul 2021 13:41:08 +0300 Subject: [PATCH 2/2] Apply review comments Signed-off-by: Sergey Kanaev --- sycl/source/detail/scheduler/commands.cpp | 74 +++++++++++++---------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/sycl/source/detail/scheduler/commands.cpp b/sycl/source/detail/scheduler/commands.cpp index 139c68b68f95b..d6514c90c014a 100644 --- a/sycl/source/detail/scheduler/commands.cpp +++ b/sycl/source/detail/scheduler/commands.cpp @@ -185,18 +185,12 @@ class DispatchHostTask { // other available job and resume once all required events are ready. for (auto &PluginWithEvents : RequiredEventsPerPlugin) { std::vector RawEvents = getPiEvents(PluginWithEvents.second); - try { - PluginWithEvents.first->call(RawEvents.size(), - RawEvents.data()); - } catch (const sycl::exception &E) { - CGHostTask &HostTask = static_cast(MThisCmd->getCG()); - HostTask.MQueue->reportAsyncException(std::current_exception()); - return (pi_result)E.get_cl_code(); - } catch (...) { - CGHostTask &HostTask = static_cast(MThisCmd->getCG()); - HostTask.MQueue->reportAsyncException(std::current_exception()); - return PI_ERROR_UNKNOWN; - } + pi_result Error = + PluginWithEvents.first->call_nocheck( + RawEvents.size(), RawEvents.data()); + + if (Error != PI_SUCCESS) + return Error; } // Wait for dependency host events. @@ -208,28 +202,9 @@ class DispatchHostTask { return PI_SUCCESS; } -public: - DispatchHostTask(ExecCGCommand *ThisCmd, - std::vector ReqToMem) - : MThisCmd{ThisCmd}, MReqToMem(std::move(ReqToMem)) {} - - void operator()() const { - assert(MThisCmd->getCG().getType() == CG::CGTYPE::CODEPLAY_HOST_TASK); - + pi_result executeHostTask() const { CGHostTask &HostTask = static_cast(MThisCmd->getCG()); - pi_result WaitResult = waitForEvents(); - if (WaitResult != PI_SUCCESS) { - std::exception_ptr EPtr = std::make_exception_ptr(sycl::runtime_error( - std::string("Couldn't wait for host-task's dependencies"), - WaitResult)); - HostTask.MQueue->reportAsyncException(EPtr); - - // reset host-task's lambda and quit - HostTask.MHostTask.reset(); - return; - } - try { // we're ready to call the user-defined lambda now if (HostTask.MHostTask->isInteropTask()) { @@ -242,10 +217,16 @@ class DispatchHostTask { HostTask.MHostTask->call(); } catch (...) { HostTask.MQueue->reportAsyncException(std::current_exception()); + + return PI_ERROR_UNKNOWN; } HostTask.MHostTask.reset(); + return PI_SUCCESS; + } + + void unblockGraph() const { // unblock user empty command here EmptyCommand *EmptyCmd = MThisCmd->MEmptyCmd; assert(EmptyCmd && "No empty command found"); @@ -271,6 +252,35 @@ class DispatchHostTask { Scheduler::enqueueLeavesOfReqUnlocked(Dep.MDepRequirement); } } + +public: + DispatchHostTask(ExecCGCommand *ThisCmd, + std::vector ReqToMem) + : MThisCmd{ThisCmd}, MReqToMem(std::move(ReqToMem)) {} + + void operator()() const { + assert(MThisCmd->getCG().getType() == CG::CGTYPE::CODEPLAY_HOST_TASK); + + CGHostTask &HostTask = static_cast(MThisCmd->getCG()); + + pi_result WaitResult = waitForEvents(); + if (WaitResult != PI_SUCCESS) { + std::exception_ptr EPtr = std::make_exception_ptr(sycl::runtime_error( + std::string("Couldn't wait for host-task's dependencies"), + WaitResult)); + HostTask.MQueue->reportAsyncException(EPtr); + + // reset host-task's lambda and quit + HostTask.MHostTask.reset(); + return; + } + + if (executeHostTask() != PI_SUCCESS) + // The failure was reported already. No need to duplicate it here. + return; + + unblockGraph(); + } }; void Command::waitForPreparedHostEvents() const {