Repository navigation
[tinker] Free the colocate placement group after a failed model build - #2504
Open
spicysharkco wants to merge 1 commit into
Open
spicysharkco wants to merge 1 commit into
spicysharkco wants to merge 1 commit into
Conversation
With colocate_all the Tinker backend reserves every GPU through a placement group before it builds the policy workers. The model id is registered only after the build succeeds, and delete_model is the only teardown path, so a build that raised left the placement group and the backend state behind. The next create_model then waited for a second full-GPU placement group and failed after SKYRL_RAY_PG_TIMEOUT_IN_S. create_model now discards that state when the first policy build raises: it removes the placement group, which also kills the workers scheduled on it, and resets the backend so a retry starts clean. The original error is re-raised, and a failure while removing the group is logged instead of masking it. _create_colocate_pg also removes a placement group that never became ready, with the same logging. Ray keeps such a request queued, and it would grab the GPUs as soon as they free up. Fixes NovaSky-AI#2482
Contributor
There was a problem hiding this comment.
Code Review
This pull request introduces robust error handling and cleanup mechanisms during model creation in the SkyRL training backend. Specifically, if a policy model fails to build or if a Ray placement group fails to become ready, the backend now properly discards the failed runtime state and removes the placement group to free up GPU resources. Additionally, a comprehensive suite of unit tests has been added to verify these cleanup behaviors under various failure scenarios. There are no review comments to address, and the changes look solid.
Contributor
[Medium impact] The PR appears safe to merge.
|
This branch has not been deployed
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What does this PR do?
Releases the colocate placement group, and resets the backend, when the first policy model fails to build in
SkyRLTrainBackend.create_model.TLDR: with
colocate_all=Truea failed firstcreate_modelleft every GPU reserved with no model id to delete it by, so each latercreate_modeltimed out waiting for GPUs the failed attempt still held.create_modelnow tears that state down before re-raising. This follows the approach proposed in the issue.Fixes #2482
Why it happens
create_modelcalls_create_colocate_pg(), which reserves every GPU through a Ray placement group, before it builds the policy workers._build_policyreturns, anddelete_modelis the only teardown path. It looks the model up first, so it cannot run for a model that was never registered._cfgand_colocate_pgset, the placement group reserved, and any workers already scheduled on it alive._dispatchis only assigned at the end of_build_policy, so the nextcreate_modeltakes the first-time path again and requests a second full-GPU placement group. That request waitsSKYRL_RAY_PG_TIMEOUT_IN_Sand fails, and so does every later attempt, until the server is restarted.There is a second, smaller leak inside
_create_colocate_pg: whenget_ray_pg_ready_with_timeoutraises, the pending request stays queued in Ray and would reserve the GPUs as soon as they free up.Solution
create_modelwraps the first-model path, from_create_colocate_pg()to the end of the policy build, in atry/except. On failure it calls the new_discard_failed_policy_runtime()and re-raises the original error._discard_failed_policy_runtime()clears_cfg,_dispatchand_colocate_pg, then removes the placement group withray.util.remove_placement_group. Removing the group also kills the workers scheduled on it: the Ray placement group documentation states that actors and tasks still using the reserved resources are forcefully killed on removal. If the removal itself fails, the error is logged as a warning so it does not hide the build error._create_colocate_pgremoves the pending placement group before re-raising the readiness timeout, and logs a warning instead of replacing the timeout error if that removal fails.Considered and left out:
delete_model: there is no registered model to delete, so this path cannot be reached.delete_modelcould then reach it, but the id would look like a live model and a retry with the same id would fail with "already exists".colocate_all=Falsethere is no colocate placement group, so only the backend state is reset. When no placement group is passed in,PPORayActorGroup._initiate_actorscreates its own on nodes with more than one GPU and never removes it, so that reservation can still leak after a failed build. This PR does not address it.Related: #2464 also changes
create_model. Its backend changes apply cleanly on top of this branch.Test plan
tests/tinker/skyrl_train/test_create_model_failure_cleanup.pymocks Ray and the worker build, so it needs no GPU:_build_policyremoves the colocate placement group and resets_cfg,_dispatch,_colocate_pg, the model registries and the LoRA signature;create_modelreserves a new placement group and registers the model, with the first group removed exactly once;colocate_all=Falsethe backend state is reset and no placement group is removed;remove_placement_groupdoes not replace the build error;remove_placement_groupon that path is logged as a warning and the timeout error still propagates.The existing warm-runtime and runtime-role tests cover the unchanged success paths of
create_model.Validation
CPU only, no GPU. On macOS the
fsdpextra only installs on Linux, so I ran the same command with--with torch --with transformersadded and the FSDP worker module stubbed by the new test file.ruff0.11.9 andblack24.10.0 report no changes on the two touched files.I have not reproduced the failure on a multi-GPU machine; the tests exercise the same control flow with mocked Ray calls.
Note
Medium Risk
Changes first-time policy initialization and Ray GPU reservation teardown on error paths; success paths are unchanged but failures now force-kill workers tied to the placement group.
Overview
Fixes a GPU leak when the first policy
create_modelfails undercolocate_all: Ray placement groups and partial runtime state were left behind becausedelete_modelonly runs for registered model IDs.create_modelnow wraps first-time policy setup (colocate placement group reservation through_build_policy) intry/except. On any failure it calls_discard_failed_policy_runtime(), which clears_cfg,_dispatch, and_colocate_pg, removes the colocate placement group when present, then re-raises the original error. Failedremove_placement_groupcalls are logged as warnings so cleanup issues do not mask the build failure._create_colocate_pgalso removes a placement group that never becomes ready before propagating the readiness timeout, with the same best-effort removal behavior.New CPU-only tests in
test_create_model_failure_cleanup.pycover failed builds, retry after failure, non-colocate reset, and placement-group timeout paths.Reviewed by Cursor Bugbot for commit ab05ab8. Bugbot is set up for automated code reviews on this repo. Configure here.