[GLM-5.2] Improve optimizer and checkpoint coverage - #1986
Open
jayhenry wants to merge 7 commits into
Open
Conversation
DCP resume materializes temporary model and optimizer state that can remain cached until the first training step, starving NCCL allocations. Collect Python garbage and empty the device cache after the complete checkpoint state has been restored.
Report per-rank allocated, reserved, free, and total device memory after checkpoint garbage collection and cache release so large-scale resume runs can verify the recovered headroom.
A resumed process loads optimizer states before its cold first forward/backward, causing their memory to overlap the compilation peak and starve NCCL allocations. Temporarily offload restored GPU optimizer tensors to CPU, then restore each tensor to its original device at the first optimizer-step boundary.
Expose offload_optimizer_first_step on LoadCheckpointConfig and use the existing put_optimizer_to_device API directly. Trainer moves optimizer state to CPU after checkpoint load and back to the training device after the first gradient reduction, without maintaining a separate engine restore plan.
Collaborator
Author
|
@claude review |
Collaborator
Author
|
@claude review code, and approve if it's fine |
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.
Summary
OPTIMIZERwhile keeping AdamW as the default.no_grad, preventing DCP resume from expecting optimizer states that are absent from trained checkpoints.LoadCheckpointConfig.offload_optimizer_first_stepas an opt-in control for cold resume memory: Trainer moves optimizer state to CPU after checkpoint load and moves it back to the training device after the first gradient reduction, usingTrainEngine.put_optimizer_to_devicedirectly.Root cause
A fresh training process creates Adam states only after its cold first forward/backward. A resumed process instead loads those states before that cold step, adding about 25.8 GB per rank to the compilation/backward peak. The resulting memory pressure first surfaced in NCCL gradient all-reduce; DeepEP and watchdog timeouts were downstream failures. Emptying the allocator cache was valid but insufficient because the restored optimizer tensors are live state rather than cache.
Testing
tests/engine/test_glm52_moe_train_engine.py::TestGlm52CheckpointEngine::test_dcp_round_trip_preserves_model_and_optimizer: passed on two H200 GPUs. The real GLM-5.2 EP2 engine loads DCP state, keeps optimizer tensors on CPU through forward/backward/all-reduce, moves them back to CUDA, and completes a valid AdamW step.tests/train/test_trainer.py::test_resume_and_load_checkpoint_cfg: passed; the enabled switch produces exactly onecpu -> cudatransfer around the first resumed step.tests/train/test_trainer.py::TestTrainerSaveHF::test_resume: passed; the default-disabled path preserves existing resume behavior.These changes make GLM-5.2 checkpoint resume match both the no-grad DSA execution path and the memory lifecycle of a fresh process while keeping first-step optimizer offload explicitly configurable.