Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SYCL] Defer buffer release when no host memory to be updated #6837

Merged
merged 68 commits into from
Dec 8, 2022
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
0601210
[SYCL] Mark mem object which may have not blocking dtor according to …
KseniyaTikhomirova Sep 16, 2022
aff3be6
Add draft how to delay buffer_impl release
KseniyaTikhomirova Sep 21, 2022
1195b59
Update symbols for non-breaking change
KseniyaTikhomirova Sep 21, 2022
8d05802
Update abi test vtable.cpp - non-breaking change
KseniyaTikhomirova Sep 21, 2022
b54b8e4
Update SYCL_MINOR_VERSION for non-breaking ABI change
KseniyaTikhomirova Sep 21, 2022
965a015
Remove ABI break
KseniyaTikhomirova Sep 21, 2022
27ccbff
Update symbols to new version
KseniyaTikhomirova Sep 21, 2022
9540fe0
Tiny rename
KseniyaTikhomirova Sep 21, 2022
c00c7cb
Revert "Update abi test vtable.cpp - non-breaking change"
KseniyaTikhomirova Sep 21, 2022
661dace
Remove isDefault method, reimplemented
KseniyaTikhomirova Sep 21, 2022
6615db3
Fix symbols again
KseniyaTikhomirova Sep 21, 2022
8174dc3
Add handling of deferred mem objects release
KseniyaTikhomirova Sep 22, 2022
d55405e
Remove unused function and restore XPTI traces collection
KseniyaTikhomirova Sep 22, 2022
bb2c4fb
Add skeleton for unit test
KseniyaTikhomirova Sep 22, 2022
5db9e85
Fix shared_ptr use_count check
KseniyaTikhomirova Sep 23, 2022
53a1892
Test draft
KseniyaTikhomirova Sep 23, 2022
4b0a3fa
[SYCL] Align usm_allocator ctor and operators with SYCCL2020
KseniyaTikhomirova Sep 23, 2022
8daea20
Update attach scheduler logic
KseniyaTikhomirova Sep 26, 2022
c855f13
Make cleanup iterative
KseniyaTikhomirova Sep 28, 2022
8dbcd1c
Fix test utils impl error
KseniyaTikhomirova Sep 28, 2022
0f61c64
Add other tests for buffer contructors
KseniyaTikhomirova Sep 28, 2022
ddf215b
Other tests for high level buffer destruction deferring logic
KseniyaTikhomirova Sep 29, 2022
23bea82
Add unittest for waitForRecordToFinish
KseniyaTikhomirova Oct 3, 2022
aa41d76
Remove debug flags uploaded by mistake
KseniyaTikhomirova Oct 3, 2022
e296d03
Merge branch 'sycl' into buff_detach
KseniyaTikhomirova Oct 3, 2022
179c472
Fix clang-format
KseniyaTikhomirova Oct 3, 2022
2076c7c
Update test to not keep ill-formed objects
KseniyaTikhomirova Oct 4, 2022
e911d0a
Check command destruction
KseniyaTikhomirova Oct 4, 2022
81c2b09
Fix clang-format
KseniyaTikhomirova Oct 4, 2022
edcfcfc
Handle set_final_data usage
KseniyaTikhomirova Oct 4, 2022
b5e85de
Fix code-review comments (round 1)
KseniyaTikhomirova Oct 5, 2022
a5980a0
Fix missed comments
KseniyaTikhomirova Oct 5, 2022
ac06f1b
Merge branch 'sycl' into buff_detach
KseniyaTikhomirova Oct 5, 2022
09b8359
Remove nagation from variable name and logic
KseniyaTikhomirova Oct 5, 2022
1e75448
Simplify deferred mem objects release - do not aggregate to capture lock
KseniyaTikhomirova Oct 5, 2022
484b1cf
Return trace of stream buffer emptyness to scheduler destructor
KseniyaTikhomirova Oct 5, 2022
1061322
Fix comments (round 2)
KseniyaTikhomirova Oct 7, 2022
d4537a3
Fix comments (round 3)
KseniyaTikhomirova Oct 7, 2022
342ff91
Fix build
KseniyaTikhomirova Oct 7, 2022
fdab0e7
Fix comments & tests (round 4)
KseniyaTikhomirova Oct 7, 2022
0872d7c
Predict comments: restore removeMemoryObject content
KseniyaTikhomirova Oct 7, 2022
3a25f1e
Fix root cause of hang when host task is not even started upon releas…
KseniyaTikhomirova Oct 11, 2022
28f008d
Fix comments (round n)
KseniyaTikhomirova Oct 14, 2022
92b5e15
Merge branch 'sycl' into buff_detach
KseniyaTikhomirova Oct 17, 2022
6247f8a
[ESIMD] Implement piEventGetInfo for event execution status
KseniyaTikhomirova Oct 18, 2022
4133862
Move comment to the right place
KseniyaTikhomirova Oct 18, 2022
79b2125
cv.notify_all should not be called under mutex paired with cv
KseniyaTikhomirova Oct 19, 2022
868973c
Remove default allocator check after SYCL2020 update
KseniyaTikhomirova Oct 21, 2022
1bc8e57
Update unittests due to default allocator check removal
KseniyaTikhomirova Oct 21, 2022
6e0943b
Update symbols after parameter removal
KseniyaTikhomirova Oct 21, 2022
1c62d08
Try to align hip context destruction handling with cuda WA
KseniyaTikhomirova Oct 26, 2022
30dfaf2
Merge branch 'sycl' into buff_detach
KseniyaTikhomirova Oct 27, 2022
60e3011
Fix unit test after mock plugin rework
KseniyaTikhomirova Nov 7, 2022
6964876
Merge branch 'sycl' into buff_detach
KseniyaTikhomirova Nov 16, 2022
3d5315e
DRAFT: try to release scheduler resources earlier using thread_local …
KseniyaTikhomirova Nov 16, 2022
467a9ea
Draft: try to release scheduler resources earlier, fix counter declar…
KseniyaTikhomirova Nov 17, 2022
0b9032a
Release scheduler resources earlier
KseniyaTikhomirova Nov 16, 2022
9d570ce
change location for buff release attempt
KseniyaTikhomirova Dec 5, 2022
c6d5dc7
Code cleanup
KseniyaTikhomirova Dec 6, 2022
a0b37ef
Code cleanup Part 2
KseniyaTikhomirova Dec 6, 2022
619ee4e
Revert "Try to align hip context destruction handling with cuda WA"
KseniyaTikhomirova Dec 6, 2022
3187f0a
Return cleanup deferred buffers to cleanupCommands call
KseniyaTikhomirova Dec 6, 2022
dbe88e2
Remove unnecessary variable in ObjectRefCounter
KseniyaTikhomirova Dec 6, 2022
06e2608
Fix hang
KseniyaTikhomirova Dec 6, 2022
71e9048
Fix comments
KseniyaTikhomirova Dec 6, 2022
a89e577
Merge branch 'sycl' into buff_detach
KseniyaTikhomirova Dec 6, 2022
ceea7f8
Prevent warning as error for release build
KseniyaTikhomirova Dec 7, 2022
1f201a9
wprotectMDeferredMemObjRelease modification with mutex
KseniyaTikhomirova Dec 7, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sycl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ include(SYCLUtils)
# The change in SYCL_MAJOR_VERSION must be accompanied with the same update in
# llvm/clang/lib/Driver/CMakeLists.txt.
set(SYCL_MAJOR_VERSION 6)
set(SYCL_MINOR_VERSION 0)
set(SYCL_MINOR_VERSION 1)
KseniyaTikhomirova marked this conversation as resolved.
Show resolved Hide resolved
romanovvlad marked this conversation as resolved.
Show resolved Hide resolved
set(SYCL_PATCH_VERSION 0)
set(SYCL_DEV_ABI_VERSION 0)
if (SYCL_ADD_DEV_VERSION_POSTFIX)
Expand Down
8 changes: 7 additions & 1 deletion sycl/include/sycl/buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ class __SYCL_EXPORT buffer_plain {

size_t getSize() const;

void handleRelease(bool DefaultAllocator) const;

std::shared_ptr<detail::buffer_impl> impl;
};

Expand Down Expand Up @@ -457,7 +459,11 @@ class buffer : public detail::buffer_plain {

buffer &operator=(buffer &&rhs) = default;

~buffer() = default;
~buffer() {
buffer_plain::handleRelease(
std::is_same<AllocatorT,
detail::sycl_memory_object_allocator<T>>::value);
romanovvlad marked this conversation as resolved.
Show resolved Hide resolved
}
KseniyaTikhomirova marked this conversation as resolved.
Show resolved Hide resolved

bool operator==(const buffer &rhs) const { return impl == rhs.impl; }

Expand Down
1 change: 0 additions & 1 deletion sycl/include/sycl/detail/sycl_mem_obj_allocator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ class SYCLMemObjAllocatorHolder : public SYCLMemObjAllocator {
}

virtual std::size_t getValueSize() const override { return MValueSize; }

protected:
virtual void *getAllocatorImpl() override { return &MAllocator; }

Expand Down
8 changes: 4 additions & 4 deletions sycl/include/sycl/usm/usm_allocator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ class usm_allocator {
AllocKind != usm::alloc::device,
"usm_allocator does not support AllocKind == usm::alloc::device");

usm_allocator() noexcept = delete;
usm_allocator() = delete;
usm_allocator(const context &Ctxt, const device &Dev,
const property_list &PropList = {}) noexcept
const property_list &PropList = {})
: MContext(Ctxt), MDevice(Dev), MPropList(PropList) {}
usm_allocator(const queue &Q, const property_list &PropList = {}) noexcept
usm_allocator(const queue &Q, const property_list &PropList = {})
: MContext(Q.get_context()), MDevice(Q.get_device()),
MPropList(PropList) {}
usm_allocator(const usm_allocator &) noexcept = default;
usm_allocator(const usm_allocator &) = default;
usm_allocator(usm_allocator &&) noexcept = default;
usm_allocator &operator=(const usm_allocator &Other) {
MContext = Other.MContext;
Expand Down
5 changes: 5 additions & 0 deletions sycl/source/buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ void buffer_plain::addOrReplaceAccessorProperties(

size_t buffer_plain::getSize() const { return impl->getSizeInBytes(); }

void buffer_plain::handleRelease(bool DefaultAllocator) const {
if (impl.use_count() == 1)
romanovvlad marked this conversation as resolved.
Show resolved Hide resolved
impl->detachMemoryObject(impl, DefaultAllocator);
}

} // namespace detail
} // __SYCL_INLINE_VER_NAMESPACE(_V1)
} // namespace sycl
5 changes: 5 additions & 0 deletions sycl/source/detail/event_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,11 @@ void event_impl::cleanDepEventsThroughOneLevel() {
}
}

bool event_impl::isCompleted() {
return get_info<info::event::command_execution_status>() ==
info::event_command_status::complete;
}

} // namespace detail
} // __SYCL_INLINE_VER_NAMESPACE(_V1)
} // namespace sycl
2 changes: 2 additions & 0 deletions sycl/source/detail/event_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ class event_impl {
/// state.
bool isInitialized() const noexcept { return MIsInitialized; }

bool isCompleted();
romanovvlad marked this conversation as resolved.
Show resolved Hide resolved

private:
// When instrumentation is enabled emits trace event for event wait begin and
// returns the telemetry event generated for the wait
Expand Down
11 changes: 11 additions & 0 deletions sycl/source/detail/global_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ T &GlobalHandler::getOrCreate(InstWithLock<T> &IWL, Types... Args) {
return *IWL.Inst;
}

void GlobalHandler::attachScheduler(Scheduler *scheduler) {
romanovvlad marked this conversation as resolved.
Show resolved Hide resolved
// Test method, do not protect with lock since releaseResources will cause dead lock due to host queue release
// const LockGuard Lock{MScheduler.Lock};
if (MScheduler.Inst)
MScheduler.Inst->releaseResources();

MScheduler.Inst.reset(scheduler);
}

Scheduler &GlobalHandler::getScheduler() { return getOrCreate(MScheduler); }

ProgramManager &GlobalHandler::getProgramManager() {
Expand Down Expand Up @@ -149,6 +158,8 @@ void shutdown() {

// First, release resources, that may access plugins.
GlobalHandler::instance().MPlatformCache.Inst.reset(nullptr);
if (GlobalHandler::instance().MScheduler.Inst)
GlobalHandler::instance().MScheduler.Inst->releaseResources();
GlobalHandler::instance().MScheduler.Inst.reset(nullptr);
GlobalHandler::instance().MProgramManager.Inst.reset(nullptr);

Expand Down
3 changes: 3 additions & 0 deletions sycl/source/detail/global_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ class GlobalHandler {

void unloadPlugins();

// For testing purposes only
void attachScheduler(Scheduler *scheduler);

private:
friend void releaseDefaultContexts();
friend void shutdown();
Expand Down
197 changes: 158 additions & 39 deletions sycl/source/detail/scheduler/scheduler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,51 +26,71 @@ namespace sycl {
__SYCL_INLINE_VER_NAMESPACE(_V1) {
namespace detail {

void Scheduler::waitForRecordToFinish(MemObjRecord *Record,
ReadLockT &GraphReadLock) {
#ifdef XPTI_ENABLE_INSTRUMENTATION
// Will contain the list of dependencies for the Release Command
std::set<Command *> DepCommands;
#endif
bool Scheduler::waitForRecordToFinish(MemObjRecord *Record,
ReadLockT &GraphReadLock,
bool ForceWait) {
assert(Record);
std::vector<Command *> ToCleanUp;
for (Command *Cmd : Record->MReadLeaves) {
EnqueueResultT Res;
bool Enqueued = GraphProcessor::enqueueCommand(Cmd, Res, ToCleanUp);
if (!Enqueued && EnqueueResultT::SyclEnqueueFailed == Res.MResult)
throw runtime_error("Enqueue process failed.",
PI_ERROR_INVALID_OPERATION);
#ifdef XPTI_ENABLE_INSTRUMENTATION
// Capture the dependencies
DepCommands.insert(Cmd);
#endif
GraphProcessor::waitForEvent(Cmd->getEvent(), GraphReadLock, ToCleanUp);
if (Cmd->getEvent()->isCompleted())
continue;
if (ForceWait) {
EnqueueResultT Res;
bool Enqueued = GraphProcessor::enqueueCommand(Cmd, Res, ToCleanUp);
if (!Enqueued && EnqueueResultT::SyclEnqueueFailed == Res.MResult)
throw runtime_error("Enqueue process failed.",
PI_ERROR_INVALID_OPERATION);
GraphProcessor::waitForEvent(Cmd->getEvent(), GraphReadLock, ToCleanUp);
} else
return false;
}
for (Command *Cmd : Record->MWriteLeaves) {
EnqueueResultT Res;
bool Enqueued = GraphProcessor::enqueueCommand(Cmd, Res, ToCleanUp);
if (!Enqueued && EnqueueResultT::SyclEnqueueFailed == Res.MResult)
throw runtime_error("Enqueue process failed.",
PI_ERROR_INVALID_OPERATION);
#ifdef XPTI_ENABLE_INSTRUMENTATION
DepCommands.insert(Cmd);
#endif
GraphProcessor::waitForEvent(Cmd->getEvent(), GraphReadLock, ToCleanUp);
if (Cmd->getEvent()->isCompleted())
continue;
if (ForceWait) {
EnqueueResultT Res;
bool Enqueued = GraphProcessor::enqueueCommand(Cmd, Res, ToCleanUp);
if (!Enqueued && EnqueueResultT::SyclEnqueueFailed == Res.MResult)
throw runtime_error("Enqueue process failed.",
PI_ERROR_INVALID_OPERATION);
GraphProcessor::waitForEvent(Cmd->getEvent(), GraphReadLock, ToCleanUp);
} else
return false;
}
// all dependencies is completed and we can enqueue all ReleaseCmds in advance
for (AllocaCommandBase *AllocaCmd : Record->MAllocaCommands) {
Command *ReleaseCmd = AllocaCmd->getReleaseCmd();
EnqueueResultT Res;
bool Enqueued = GraphProcessor::enqueueCommand(ReleaseCmd, Res, ToCleanUp);
if (!Enqueued && EnqueueResultT::SyclEnqueueFailed == Res.MResult)
throw runtime_error("Enqueue process failed.",
PI_ERROR_INVALID_OPERATION);
if (ReleaseCmd->isSuccessfullyEnqueued())
continue;
#ifdef XPTI_ENABLE_INSTRUMENTATION
// Will contain the list of dependencies for the Release Command
std::set<Command *> DepCommands;
// Capture the read dependencies
for (Command *Cmd : Record->MWriteLeaves)
DepCommands.insert(Cmd);
for (Command *Cmd : Record->MReadLeaves)
DepCommands.insert(Cmd);
// Report these dependencies to the Command so these dependencies can be
// reported as edges
ReleaseCmd->resolveReleaseDependencies(DepCommands);
#endif
GraphProcessor::waitForEvent(ReleaseCmd->getEvent(), GraphReadLock,
ToCleanUp);
EnqueueResultT Res;
bool Enqueued = GraphProcessor::enqueueCommand(ReleaseCmd, Res, ToCleanUp);
if (!Enqueued && EnqueueResultT::SyclEnqueueFailed == Res.MResult)
throw runtime_error("Enqueue process failed.",
PI_ERROR_INVALID_OPERATION);
}
// enqueue is fully done and we can check if ReleaseCmd is completed
for (AllocaCommandBase *AllocaCmd : Record->MAllocaCommands) {
Command *Cmd = AllocaCmd->getReleaseCmd();
if (Cmd->getEvent()->isCompleted())
continue;
if (ForceWait)
GraphProcessor::waitForEvent(Cmd->getEvent(), GraphReadLock, ToCleanUp);
else
return false;
}
return true;
}

EventImplPtr Scheduler::addCG(std::unique_ptr<detail::CG> CommandGroup,
Expand Down Expand Up @@ -258,6 +278,18 @@ void Scheduler::cleanupFinishedCommands(EventImplPtr FinishedEvent) {
deallocateStreams(StreamsToDeallocate);
}

inline void Scheduler::releaseMemObjRecord(
detail::SYCLMemObjI *MemObj,
std::vector<std::shared_ptr<stream_impl>> &StreamsToDeallocate,
std::vector<std::shared_ptr<const void>> &AuxResourcesToDeallocate) {
MemObjRecord *Record = MGraphBuilder.getMemObjRecord(MemObj);
assert(Record);
MGraphBuilder.decrementLeafCountersForRecord(Record);
MGraphBuilder.cleanupCommandsForRecord(Record, StreamsToDeallocate,
AuxResourcesToDeallocate);
MGraphBuilder.removeRecordForMemObj(MemObj);
}

void Scheduler::removeMemoryObject(detail::SYCLMemObjI *MemObj) {
// We are going to traverse a graph of finished commands. Gather stream
// objects from these commands if any and deallocate buffers for these stream
Expand All @@ -283,16 +315,14 @@ void Scheduler::removeMemoryObject(detail::SYCLMemObjI *MemObj) {
// No operations were performed on the mem object
return;

waitForRecordToFinish(Record, Lock);
waitForRecordToFinish(Record, Lock, true);
romanovvlad marked this conversation as resolved.
Show resolved Hide resolved
}

{
WriteLockT Lock(MGraphLock, std::defer_lock);
acquireWriteLock(Lock);
MGraphBuilder.decrementLeafCountersForRecord(Record);
MGraphBuilder.cleanupCommandsForRecord(Record, StreamsToDeallocate,
AuxResourcesToDeallocate);
MGraphBuilder.removeRecordForMemObj(MemObj);
releaseMemObjRecord(MemObj, StreamsToDeallocate,
AuxResourcesToDeallocate);
}
}
deallocateStreams(StreamsToDeallocate);
Expand Down Expand Up @@ -395,6 +425,15 @@ Scheduler::Scheduler() {
}

Scheduler::~Scheduler() {
// Please be aware that releaseResources should be called before deletion of Scheduler.
// Otherwise there can be the case when objects Scheduler keeps as fields may need Scheduler
// for their release and they work with Scheduler via GlobalHandler::getScheduler that will create new Scheduler object.
// Still keep it here but it should no almost nothing if releaseResources called before.
releaseResources();
}

void Scheduler::releaseResources()
{
// By specification there are several possible sync points: buffer
romanovvlad marked this conversation as resolved.
Show resolved Hide resolved
// destruction, wait() method of a queue or event. Stream doesn't introduce
// any synchronization point. It is guaranteed that stream is flushed and
Expand All @@ -414,6 +453,14 @@ Scheduler::~Scheduler() {
// haven't been freed because of the graph mutex being locked at the time,
// clean them up now.
cleanupCommands({});
DefaultHostQueue.reset();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to be unsafe to release DefaultHostQueue here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets first get results if the solution helps


// 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 cleanup commands related to this record,
// command may have last reference to queue_impl, ~queue_impl is called and buffer for assert (which is created 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(!isNoDeferredMemObjects())
cleanupDeferredMemObjects(true);
romanovvlad marked this conversation as resolved.
Show resolved Hide resolved
}

void Scheduler::acquireWriteLock(WriteLockT &Lock) {
Expand Down Expand Up @@ -442,8 +489,8 @@ MemObjRecord *Scheduler::getMemObjRecord(const Requirement *const Req) {
}

void Scheduler::cleanupCommands(const std::vector<Command *> &Cmds) {
if (Cmds.empty())
{
cleanupDeferredMemObjects(false);
romanovvlad marked this conversation as resolved.
Show resolved Hide resolved
if (Cmds.empty()) {
std::lock_guard<std::mutex> Lock{MDeferredCleanupMutex};
if (MDeferredCleanupCommands.empty())
return;
Expand Down Expand Up @@ -472,6 +519,78 @@ void Scheduler::cleanupCommands(const std::vector<Command *> &Cmds) {
}
}

void Scheduler::deferMemObjRelease(const std::shared_ptr<SYCLMemObjI> &MemObj) {
{
std::lock_guard<std::mutex> Lock{MDeferredMemReleaseMutex};
MDeferredMemObjRelease.push_back(MemObj);
}
cleanupDeferredMemObjects(false);
romanovvlad marked this conversation as resolved.
Show resolved Hide resolved
}

inline bool Scheduler::isNoDeferredMemObjects()
{
std::lock_guard<std::mutex> Lock{MDeferredMemReleaseMutex};
return MDeferredMemObjRelease.empty();
}

void Scheduler::cleanupDeferredMemObjects(bool ForceWait) {
romanovvlad marked this conversation as resolved.
Show resolved Hide resolved
if (isNoDeferredMemObjects())
return;

// Need to aggregate ready to release object to acquire write lock once.
std::list<std::shared_ptr<SYCLMemObjI>> ObjsReadyToRelease;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
std::list<std::shared_ptr<SYCLMemObjI>> ObjsReadyToRelease;
std::vector<std::shared_ptr<SYCLMemObjI>> ObjsReadyToRelease;

Probably, it makes sense to use std::vector here as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 28f008d

{
ReadLockT Lock(MGraphLock, std::try_to_lock);
// if we need blocking mode - force lock waiting
if (!Lock.owns_lock() && ForceWait)
Lock.lock();
if (Lock.owns_lock()) {
romanovvlad marked this conversation as resolved.
Show resolved Hide resolved
{
// Not expected that ForceWait == true with be used in parallel with
romanovvlad marked this conversation as resolved.
Show resolved Hide resolved
// adding MemObj to storage, no such scenario.
std::lock_guard<std::mutex> LockDef{MDeferredMemReleaseMutex};
auto MemObjIt = MDeferredMemObjRelease.begin();
while (MemObjIt != MDeferredMemObjRelease.end()) {
MemObjRecord *Record = MGraphBuilder.getMemObjRecord((*MemObjIt).get());
if (!Record) {
// Just trigger delete since no operations on object was perfromed and
romanovvlad marked this conversation as resolved.
Show resolved Hide resolved
// no commands and other to wait for
MemObjIt = MDeferredMemObjRelease.erase(MemObjIt);
continue;
}
if (!waitForRecordToFinish(Record, Lock, ForceWait)) {
MemObjIt++;
continue;
}
ObjsReadyToRelease.push_back(*MemObjIt);
MemObjIt = MDeferredMemObjRelease.erase(MemObjIt);
}
}
}
if (ObjsReadyToRelease.empty())
return;

std::vector<std::shared_ptr<stream_impl>> StreamsToDeallocate;
std::vector<std::shared_ptr<const void>> AuxResourcesToDeallocate;
{
WriteLockT Lock(MGraphLock, std::try_to_lock);
// if we need blocking mode - force lock waiting
if (!Lock.owns_lock() && ForceWait)
acquireWriteLock(Lock);
if (Lock.owns_lock()) {
for (auto &MemObj : ObjsReadyToRelease)
romanovvlad marked this conversation as resolved.
Show resolved Hide resolved
releaseMemObjRecord(MemObj.get(), StreamsToDeallocate,
AuxResourcesToDeallocate);
} else {
std::lock_guard<std::mutex> LockDef{MDeferredMemReleaseMutex};
MDeferredMemObjRelease.splice(MDeferredMemObjRelease.end(),
ObjsReadyToRelease);
}
}
deallocateStreams(StreamsToDeallocate);
// ObjsReadyToRelease leaving scope and being deleted
}
}
} // namespace detail
} // __SYCL_INLINE_VER_NAMESPACE(_V1)
} // namespace sycl
Loading