[train] Share PlacementGroupCleaner across Train runs - #65447
[train] Share PlacementGroupCleaner across Train runs#65447OneSizeFitsQuorum wants to merge 1 commit into
Conversation
816a97e to
07ef5b1
Compare
There was a problem hiding this comment.
Code Review
This pull request refactors the PlacementGroupCleaner into a shared detached actor that manages placement group cleanups for multiple Train controllers, persisting state in Ray's internal KV store to handle ungraceful controller exits and cleaner restarts. The review comments correctly identify Python 3.8 compatibility issues due to the use of removeprefix on bytes and str objects in both the implementation and the test suite, suggesting slicing as a backward-compatible alternative.
07ef5b1 to
2287932
Compare
2da5503 to
b0209cb
Compare
Use one cluster-wide detached cleaner for Train controllers and persist per-controller placement group registrations in GCS internal KV. Recover cleanup state across cleaner restarts, isolate controllers during failure handling, scope state queries to the current cluster, prune completed placement group registrations, and keep monitoring alive after unexpected state-query errors. Signed-off-by: OneSizeFitsQuorum <tanxinyu@apache.org>
bca672e to
0b212e0
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
Reviewed by Cursor Bugbot for commit 0b212e0. Configure here.
| ) | ||
| # Send placement group update to the monitor thread via queue | ||
| self._pg_queue.put(placement_group) | ||
| return not controller_is_dead |
There was a problem hiding this comment.
Live PGs cleaned after false death
High Severity
A missing or cleaning controller record is treated as terminal, and a later register_placement_group is kept for deletion. is_actor_alive also treats a missing State API result as dead. Every run has an empty-PG window after after_controller_start (and again between worker-group shutdown and restart). One transient miss can drop the live record; the next PG register is then cleaned by the shared actor and tears down an active run. The old per-controller actor exited instead, so a failed later register left the PG alone.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit 0b212e0. Configure here.


Description
Ray Train v2 currently creates one detached
PlacementGroupCleaneractor perTrain controller. Since cleaners are pinned to the head node, their memory use
grows linearly with concurrent Train runs. In the workload described in #65443,
24 cleaners use approximately 14.4 GB on the head node.
This PR replaces the per-controller actors with one cluster-wide shared
cleaner. The cleaner tracks controllers independently, so a failed controller
only triggers cleanup for its own placement groups.
The shared cleaner:
get_if_exists=True;placement groups;
Related issues
Fixes #65443.
Testing
A local end-to-end multi-job scenario used two independent drivers, each
running a real Train v2
DataParallelTrainerwith a controller, worker, andplacement group. Both runs shared one cleaner. After one driver was killed,
only its placement group was removed; the other run remained active and
completed normally. The cleaner stayed alive throughout.
Contribution notes
No other open PR referencing #65443 or matching this PlacementGroupCleaner
change was found before requesting review.
AI assistance was used for implementation, testing, and self-review of this
change.