Skip to content

[Bugfix][Training] Fix native Adam checkpoint resume and add parity checks - #427

Closed
0z5a wants to merge 2 commits into
vllm-project:0z5a-branchfrom
0z5a:fix/native-adam-checkpoint-resume
Closed

0z5a wants to merge 2 commits into
vllm-project:0z5a-branchfrom
0z5a:fix/native-adam-checkpoint-resume

Conversation

@0z5a

@0z5a 0z5a commented Sep 12, 2026 •

Copy link
Copy Markdown

Incremental review: Files changed.

Base: 0z5a-branch at 791f101e20db377b28e15f12a00863baaea2605f.

Fix native Torch Adam/AdamW checkpoint restoration in the existing Megatron Docker patch. Accept an empty fresh-optimizer load template, skip shard-copying the common scalar step, restore independent per-parameter step tensors, and remove the checkpoint-only group field.

The cleaned branch incorporates the current target base. The submitted diff contains only the Docker patch; audit runners and added test files were removed.

Validation of the implementation Result
Publication-checkout audit tests 20 passed
Repository hooks All 9 passed
Earlier Linux checks 24 passed, including 4 native Megatron optimizer tests
Patch against pinned Megatron 1dcf0dafa884ad52ffb243625717a3471643e087 Applied; optimizer source matched tested runtime
Fixed-batch processes All completed: 8 uninterrupted, 4 prefix, 4 restored updates
Compared training state Prefix and first 3 restored updates exactly matched uninterrupted training

The fixture uses full Qwen3-0.6B, BF16 model parameters, FP32 master parameters, distributed AdamW and TP=PP=CP=1. The final aggregate comparison remains unverified; additional online checkpoint-resume validation remains incomplete. The GPU fixture includes #426 as a separate runtime prerequisite. The cleanup preserves the implementation while merging current base changes; the archived GPU results precede this cleanup.

No speed or convergence improvement is established.

@read-the-docs-community

read-the-docs-community Bot commented Sep 12, 2026 •

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request updates the Megatron patch to properly handle fresh native Torch Adam/AdamW optimizers during checkpoint loading, ensuring that steps are independent and updated correctly. It also introduces a comprehensive suite of integration and unit tests to verify checkpoint resume parity. The review feedback highlights a few improvement opportunities: cleaning up the temporary directory ray_temp in the parity runner to prevent disk space accumulation, and using weights_only=True when loading PyTorch checkpoints in the audit tests to enhance security and avoid deprecation warnings.

Comment thread tests/test_checkpoint_resume_parity.py Outdated
Comment on lines +47 to +79
try:
ray_temp = tempfile.mkdtemp(prefix="vime-resume-ray-")
(output / "ray-temp-dir.txt").write_text(ray_temp + "\n")
ray.init(
address="local",
num_cpus=12,
num_gpus=1,
include_dashboard=False,
object_store_memory=2 * 1024**3,
namespace=output.name,
_temp_dir=ray_temp,
_node_ip_address="127.0.0.1",
runtime_env={"env_vars": {"VIME_RESUME_AUDIT_DIR": str(output)}},
)
spec = importlib.util.spec_from_file_location("resume_parity_train", checkout / "train.py")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
train_args = module.parse_args()
if args.stop_after is not None:
assert 0 < args.stop_after < train_args.num_rollout
# Do not change num_rollout: the scheduler horizon must be identical
# in the continuous run, split prefix, and resumed suffix.
module.range = lambda start, stop: range(start, min(stop, args.stop_after))
module.train(train_args)
(output / "train-returned.json").write_text(json.dumps({"completed": True}))
finally:
ray.shutdown()
sys.stdout.flush()
sys.stderr.flush()
for fd, original in zip([1, 2], saved_fds, strict=True):
os.dup2(original, fd)
os.close(original)
log.close()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The temporary directory ray_temp created by tempfile.mkdtemp is not cleaned up after the training and audit logs are recorded. This can lead to disk space accumulation in /tmp on test machines or CI runners over time.

Please clean up the temporary directory in the finally block using shutil.rmtree.

    ray_temp = tempfile.mkdtemp(prefix="vime-resume-ray-")
    try:
        (output / "ray-temp-dir.txt").write_text(ray_temp + "\n")
        ray.init(
            address="local",
            num_cpus=12,
            num_gpus=1,
            include_dashboard=False,
            object_store_memory=2 * 1024**3,
            namespace=output.name,
            _temp_dir=ray_temp,
            _node_ip_address="127.0.0.1",
            runtime_env={"env_vars": {"VIME_RESUME_AUDIT_DIR": str(output)}},
        )
        spec = importlib.util.spec_from_file_location("resume_parity_train", checkout / "train.py")
        module = importlib.util.module_from_spec(spec)
        spec.loader.exec_module(module)
        train_args = module.parse_args()
        if args.stop_after is not None:
            assert 0 < args.stop_after < train_args.num_rollout
            # Do not change num_rollout: the scheduler horizon must be identical
            # in the continuous run, split prefix, and resumed suffix.
            module.range = lambda start, stop: range(start, min(stop, args.stop_after))
        module.train(train_args)
        (output / "train-returned.json").write_text(json.dumps({"completed": True}))
    finally:
        ray.shutdown()
        import shutil
        shutil.rmtree(ray_temp, ignore_errors=True)
        sys.stdout.flush()
        sys.stderr.flush()
        for fd, original in zip([1, 2], saved_fds, strict=True):
            os.dup2(original, fd)
            os.close(original)
        log.close()

Comment thread tests/checkpoint_resume_audit.py Outdated
Comment on lines +197 to +198
a = torch.load(continuous / f"dumps/train_data/{rid}.pt", map_location="cpu", weights_only=False)
b = torch.load(root / f"dumps/train_data/{rid}.pt", map_location="cpu", weights_only=False)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

security-medium medium

Using weights_only=False when loading PyTorch checkpoints is a security risk and can trigger deprecation warnings in newer PyTorch versions. Since the saved training data only contains standard PyTorch tensors and basic Python types, it is safer and cleaner to use weights_only=True.

Suggested change
a = torch.load(continuous / f"dumps/train_data/{rid}.pt", map_location="cpu", weights_only=False)
b = torch.load(root / f"dumps/train_data/{rid}.pt", map_location="cpu", weights_only=False)
a = torch.load(continuous / f"dumps/train_data/{rid}.pt", map_location="cpu", weights_only=True)
b = torch.load(root / f"dumps/train_data/{rid}.pt", map_location="cpu", weights_only=True)

@pytest.mark.parametrize("key", ["tokens", "loss_masks", "log_probs", "advantages"])
def test_rejects_changed_training_batch(evidence, key):
path = evidence[2] / "dumps/train_data/1.pt"
batch = torch.load(path, weights_only=False)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

security-medium medium

Using weights_only=False when loading PyTorch checkpoints is a security risk and can trigger deprecation warnings in newer PyTorch versions. Since the saved training data only contains standard PyTorch tensors and basic Python types, it is safer and cleaner to use weights_only=True.

Suggested change
batch = torch.load(path, weights_only=False)
batch = torch.load(path, weights_only=True)

@0z5a
0z5a marked this pull request as ready for review September 13, 2026 03:55
@0z5a
0z5a changed the base branch from main to 0z5a-branch September 18, 2026 18:57
@0z5a
0z5a changed the base branch from 0z5a-branch to main September 19, 2026 01:24
@0z5a
0z5a changed the base branch from main to 0z5a-branch September 19, 2026 06:03
@0z5a
0z5a force-pushed the fix/native-adam-checkpoint-resume branch from d7ea0b7 to a3098e0 Compare September 24, 2026 05:54
Signed-off-by: 0z5a <192209249+0z5a@users.noreply.github.com>
Signed-off-by: 0z5a <dezhen.lu@student.uni-tuebingen.de>
@0z5a
0z5a force-pushed the fix/native-adam-checkpoint-resume branch from a3098e0 to f8ee091 Compare September 24, 2026 07:08
Signed-off-by: 0z5a <dezhen.lu@student.uni-tuebingen.de>
@0z5a

0z5a commented Oct 6, 2026

Copy link
Copy Markdown
Author

Superseded by #460, now merged into 0z5a-branch. The consolidated implementation and validation are retained there; closing this duplicate PR.

@0z5a 0z5a closed this Oct 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant