Skip to content

Commit

Permalink
[SYCL] Preserve in-order queue dependency chain between usm & host ta…
Browse files Browse the repository at this point in the history
…sks (#6840)

Currently last event is not updated for usm commands, so dependency
chain is incorrect if usm commands are interleaved with host tasks. Also
we need to wait if the last event is associated with host task before
submitting usm command.

E2E test: intel/llvm-test-suite#1283
  • Loading branch information
againull authored Sep 22, 2022
1 parent f3ca156 commit 067d3b3
Showing 1 changed file with 79 additions and 18 deletions.
97 changes: 79 additions & 18 deletions sycl/source/detail/queue_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,34 @@ event queue_impl::memset(const std::shared_ptr<detail::queue_impl> &Self,
getOrWaitEvents(DepEvents, MContext), nullptr);
return createDiscardedEvent();
}
RT::PiEvent NativeEvent{};
MemoryManager::fill_usm(Ptr, Self, Count, Value,
getOrWaitEvents(DepEvents, MContext), &NativeEvent);
event ResEvent;
{
// We need to submit command and update the last event under same lock if we
// have in-order queue.
auto ScopeLock = isInOrder() ? std::unique_lock(MLastEventMtx)
: std::unique_lock<std::mutex>();
// If the last submitted command in the in-order queue is host_task then
// wait for it before submitting usm command.
if (isInOrder() && (MLastCGType == CG::CGTYPE::CodeplayHostTask ||
MLastCGType == CG::CGTYPE::CodeplayInteropTask))
MLastEvent.wait();

if (MContext->is_host())
return MDiscardEvents ? createDiscardedEvent() : event();
RT::PiEvent NativeEvent{};
MemoryManager::fill_usm(Ptr, Self, Count, Value,
getOrWaitEvents(DepEvents, MContext), &NativeEvent);

event ResEvent = prepareUSMEvent(Self, NativeEvent);
if (MContext->is_host())
return MDiscardEvents ? createDiscardedEvent() : event();

ResEvent = prepareUSMEvent(Self, NativeEvent);
if (isInOrder()) {
MLastEvent = ResEvent;
// We don't create a command group for usm commands, so set it to None.
// This variable is used to perform explicit dependency management when
// required.
MLastCGType = CG::CGTYPE::None;
}
}
// Track only if we won't be able to handle it with piQueueFinish.
if (!MSupportOOO)
addSharedEvent(ResEvent);
Expand All @@ -89,14 +109,34 @@ event queue_impl::memcpy(const std::shared_ptr<detail::queue_impl> &Self,
getOrWaitEvents(DepEvents, MContext), nullptr);
return createDiscardedEvent();
}
RT::PiEvent NativeEvent{};
MemoryManager::copy_usm(Src, Self, Count, Dest,
getOrWaitEvents(DepEvents, MContext), &NativeEvent);
event ResEvent;
{
// We need to submit command and update the last event under same lock if we
// have in-order queue.
auto ScopeLock = isInOrder() ? std::unique_lock(MLastEventMtx)
: std::unique_lock<std::mutex>();
// If the last submitted command in the in-order queue is host_task then
// wait for it before submitting usm command.
if (isInOrder() && (MLastCGType == CG::CGTYPE::CodeplayHostTask ||
MLastCGType == CG::CGTYPE::CodeplayInteropTask))
MLastEvent.wait();

RT::PiEvent NativeEvent{};
MemoryManager::copy_usm(Src, Self, Count, Dest,
getOrWaitEvents(DepEvents, MContext), &NativeEvent);

if (MContext->is_host())
return MDiscardEvents ? createDiscardedEvent() : event();
if (MContext->is_host())
return MDiscardEvents ? createDiscardedEvent() : event();

event ResEvent = prepareUSMEvent(Self, NativeEvent);
ResEvent = prepareUSMEvent(Self, NativeEvent);
if (isInOrder()) {
MLastEvent = ResEvent;
// We don't create a command group for usm commands, so set it to None.
// This variable is used to perform explicit dependency management when
// required.
MLastCGType = CG::CGTYPE::None;
}
}
// Track only if we won't be able to handle it with piQueueFinish.
if (!MSupportOOO)
addSharedEvent(ResEvent);
Expand All @@ -112,14 +152,35 @@ event queue_impl::mem_advise(const std::shared_ptr<detail::queue_impl> &Self,
getOrWaitEvents(DepEvents, MContext), nullptr);
return createDiscardedEvent();
}
RT::PiEvent NativeEvent{};
MemoryManager::advise_usm(Ptr, Self, Length, Advice,
getOrWaitEvents(DepEvents, MContext), &NativeEvent);
event ResEvent;
{
// We need to submit command and update the last event under same lock if we
// have in-order queue.
auto ScopeLock = isInOrder() ? std::unique_lock(MLastEventMtx)
: std::unique_lock<std::mutex>();
// If the last submitted command in the in-order queue is host_task then
// wait for it before submitting usm command.
if (isInOrder() && (MLastCGType == CG::CGTYPE::CodeplayHostTask ||
MLastCGType == CG::CGTYPE::CodeplayInteropTask))
MLastEvent.wait();

if (MContext->is_host())
return MDiscardEvents ? createDiscardedEvent() : event();
RT::PiEvent NativeEvent{};
MemoryManager::advise_usm(Ptr, Self, Length, Advice,
getOrWaitEvents(DepEvents, MContext),
&NativeEvent);

if (MContext->is_host())
return MDiscardEvents ? createDiscardedEvent() : event();

event ResEvent = prepareUSMEvent(Self, NativeEvent);
ResEvent = prepareUSMEvent(Self, NativeEvent);
if (isInOrder()) {
MLastEvent = ResEvent;
// We don't create a command group for usm commands, so set it to None.
// This variable is used to perform explicit dependency management when
// required.
MLastCGType = CG::CGTYPE::None;
}
}
// Track only if we won't be able to handle it with piQueueFinish.
if (!MSupportOOO)
addSharedEvent(ResEvent);
Expand Down

0 comments on commit 067d3b3

Please sign in to comment.