You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[SYCL] Release deferred resources after event and queue waits - #23344
Deferred buffers, images and auxiliary resources can otherwise remain
alive until later scheduler activity or runtime shutdown. Release completed
resources after event waits, and sweep deferred resources after queue waits
so completed resources attached to other events are released too.
Use event-indexed auxiliary cleanup for targeted event waits, keeping
unrelated incomplete events from being polled. Destroy extracted resources
outside their mutex to allow destructor-triggered nested waits. Recheck
resources after slow-path waits and avoid reserving space for the entire
auxiliary-resource map when only a few entries are complete.
Publish the Scheduler pointer atomically and guard its lifetime during
wait-triggered cleanup. Preserve cleanup in wait tracing and avoid waiting
for scheduler-access guards during Windows process termination.
Add scheduler tests for nested waits, slow-path registration, targeted
event polling, scheduler lifetime synchronization, and queue-wait cleanup.
This is an improvement in resource lifetime and cleanup behavior.
It releases completed deferred resources after waits
instead of leaving them alive until later scheduler activity
or runtime shutdown. That can reduce memory retained
by long-running applications and avoid resources -
and the queues or contexts they keep alive - persisting through shutdown.
The reason will be displayed to describe this comment to others. Learn more.
Reviewed the proactive deferred-resource release in event_impl::wait() plus the supporting Scheduler::MDeferredResourcesCount atomic counter and GlobalHandler::getSchedulerIfAlive() accessor. I traced every increment/decrement site for the counter (cleanupCommands, deferMemObjRelease, cleanupDeferredMemObjects, takeAuxiliaryResources, registerAuxiliaryResources, cleanupAuxiliaryResources) against each insertion/removal from MDeferredCleanupCommands, MDeferredMemObjRelease, and MAuxiliaryResources, including the takeAuxiliaryResources merge-into-existing-entry edge case, and the bookkeeping is balanced throughout. The WaitedViaScheduler short-circuit in event_impl::wait() correctly avoids a redundant release pass when Scheduler::waitForEvent() already performed one via cleanupCommands. getSchedulerIfAlive() mirrors the existing lock-free isSchedulerAlive() pattern, so no new thread-safety concern is introduced. Relaxed memory ordering on the counter is appropriate given it's documented as a best-effort hint, with actual releases still happening under the respective mutexes. The new AuxiliaryResourcesReleasedOnWait unit test and the re-enabled Windows E2E tests (reduction_resource_leak_dw.cpp, reduction_resource_leak_usm.cpp) are consistent with and validate the stated goal. No correctness, security, or test-coverage issues found.
Wait-end trace emitted before resource release completes
sycl/source/detail/event_impl.cpp:429
trace_wait_end is emitted before this newly added work, so XPTI reports event::wait() as finished while releaseResources() is still running. Contention or cleanup cost will therefore be omitted from wait profiles and the trace's call ordering can precede the actual return. Move the instrumentation epilog after this cleanup, as queue_impl::wait() does after all of its wait work.
The scheduler slow path is not guaranteed to leave the deferred sets empty. waitForEvent() calls cleanupCommands(), which drains deferred resources before deleting the commands; those deletions can themselves defer new memory objects (the post-cleanup case documented in Scheduler::releaseResources()). Marking every slow-path wait as already cleaned therefore skips the only final pass and can still retain resources after the application's last wait. Check the counter after both wait paths; it remains lock-free and avoids the extra pass when cleanup really completed.
ldorau
changed the title
[SYCL] Proactively release deferred resources after event::wait()
[SYCL] Release deferred resources after event and queue waits
Oct 5, 2026
Deferred buffers, images and auxiliary resources can otherwise remain
alive until later scheduler activity or runtime shutdown. Release completed
resources after event waits, and sweep deferred resources after queue waits
so completed resources attached to other events are released too.
Use event-indexed auxiliary cleanup for targeted event waits, keeping
unrelated incomplete events from being polled. Destroy extracted resources
outside their mutex to allow destructor-triggered nested waits. Recheck
resources after slow-path waits and avoid reserving space for the entire
auxiliary-resource map when only a few entries are complete.
Publish the Scheduler pointer atomically and guard its lifetime during
wait-triggered cleanup. Preserve cleanup in wait tracing and avoid waiting
for scheduler-access guards during Windows process termination.
Add scheduler tests for nested waits, slow-path registration, targeted
event polling, scheduler lifetime synchronization, and queue-wait cleanup.
Fixes: intel#22233Fixes: intel#20852
Signed-off-by: Lukasz Dorau <lukasz.dorau@intel.com>
The reason will be displayed to describe this comment to others. Learn more.
Round-2 review: Re-examined the SchedulerAccess RAII guard (GlobalHandler), the atomic generation/counter bookkeeping added to Scheduler (MDeferredResourcesCount, MAuxiliaryResourcesGeneration), and the Windows shutdown-ordering fix (ProcessTerminating / stopSchedulerAccess). All increment/decrement pairs across cleanupCommands, cleanupDeferredMemObjects, registerAuxiliaryResources, takeAuxiliaryResources, and both blocking/non-blocking cleanupAuxiliaryResources paths (including the exception-retry path) are consistent. The Windows skip-wait path during process termination is correctly scoped to the case where other threads are already OS-terminated, matching the existing CanJoinThreads semantics in this file. No Critical or Important issues found in this round.
With the additional logic added to event::wait(), could you please make sure there is no performance impact for the fast path benchmarks we have (probably it makes sense to focus on the tests which include the completion path)?
The L0 loader on Windows CI (v1.32.0) does not count events created with
the core zeEventCounterBasedCreate API, so their zeEventDestroy calls are
reported by the UR_L0_LEAKS_DEBUG leak checker as a negative leak
("LEAK = -7"). This makes the re-enabled reduction_resource_leak_dw.cpp
and reduction_resource_leak_usm.cpp tests fail on Windows with
a false-positive leak.
Apply the same temporary workaround as in commit 3733672
("[SYCL][E2E] Temporarily ignore negative L0 leak counts on Windows"), see
intel@3733672
on Windows ignore only negative leak counts, so real (positive) leaks are
still detected; Linux keeps the full check. The workaround should be
reverted once the L0 loader on Windows CI is updated.
Signed-off-by: Lukasz Dorau <lukasz.dorau@intel.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Deferred buffers, images and auxiliary resources can otherwise remain
alive until later scheduler activity or runtime shutdown. Release completed
resources after event waits, and sweep deferred resources after queue waits
so completed resources attached to other events are released too.
Use event-indexed auxiliary cleanup for targeted event waits, keeping
unrelated incomplete events from being polled. Destroy extracted resources
outside their mutex to allow destructor-triggered nested waits. Recheck
resources after slow-path waits and avoid reserving space for the entire
auxiliary-resource map when only a few entries are complete.
Publish the Scheduler pointer atomically and guard its lifetime during
wait-triggered cleanup. Preserve cleanup in wait tracing and avoid waiting
for scheduler-access guards during Windows process termination.
Add scheduler tests for nested waits, slow-path registration, targeted
event polling, scheduler lifetime synchronization, and queue-wait cleanup.
This is an improvement in resource lifetime and cleanup behavior.
It releases completed deferred resources after waits
instead of leaving them alive until later scheduler activity
or runtime shutdown. That can reduce memory retained
by long-running applications and avoid resources -
and the queues or contexts they keep alive - persisting through shutdown.
Fixes: #22233
Fixes: #20852