fix: make checkpoint resume explicit and stop claiming optimizer state - #17
Merged
Conversation
Resume was implicit. train() loaded any checkpoint it found in checkpoint_dir
with no flag and no way to opt out, restoring the step counter along with the
weights — so re-running `glm-train --steps 80` after an 80-step run restored
step = 80, fell straight through the loop, and printed what looked like a
successful run having trained nothing.
Resume is now opt-in via --resume. Without it, an existing checkpoint
directory is left alone and the run starts from step 0, with a note on stdout
so a stale directory is visible rather than surprising. With it and a restored
step already at max_steps, the run fails naming both numbers instead of
exiting quietly.
save_optimizer_state claimed to save optimizer state and wrote {"step": N} —
no AdamW moments. candle keeps first_moment and second_moment in a private
VarAdamW with no accessor, so honouring that claim means writing and
maintaining our own optimizer, which is not worth it for a CPU playground with
short runs. The config field, the optimizer_step_*.json file, the empty if-let
that read it back, and the README claim are gone. What resume does restore —
weights, step counter, LR schedule position — is now documented, along with
the fact that Adam restarts cold and the loss briefly rises.
save_checkpoint also fell back to the literal name "unknown" when the
parameter and name lists disagreed in length. That collides in the safetensors
map and silently drops every parameter after the first; it now errors.
Verified end to end. Last loss before resuming was 5.0751 at step 40; the
first after was 5.1103 at step 45, and the learning rate picked up at the
right point on the cosine schedule. A cold start would have been back near
10.8.
104 tests pass, including a checkpoint round trip that asserts every parameter
matches after a save and load, and a check that the parameter and name lists
agree in length and carry no duplicates.
GitMind PR Review{'pr_url': '#17', 'repo': 'Ayyankhan101/Transformer-In-Rust', 'pr_num': '17', 'title': 'fix: make checkpoint resume explicit and stop claiming optimizer state', 'author': 'Ayyankhan101', 'additions': 206, 'deletions': 87, 'changed_files': 9, 'review': '## Summary\nAutomatic review could not be generated — please review the diff manually.\n\n## Issues\nNo significant issues found.\n\n## Verdict\n💬 NEEDS DISCUSSION\nThe automated review failed; human review required.'} Auto-generated by GitMind — AI-powered code analysis. |
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.
The last piece of the training path that was written, claimed, and never checked.
Resume was implicit, and could silently do nothing
train()loaded any checkpoint it found with no flag and no way to opt out, restoring thestep counter along with the weights. So re-running
glm-train --steps 80after an 80-steprun restored
step = 80, fell straight through the loop, and printed what looked like asuccessful run having trained nothing.
Resume is now opt-in via
--resume:save_optimizer_statedid not save optimizer stateIt wrote
{"step": N}— 16 bytes, no AdamW moments — while the README claimed "model +optimizer state", and
load_checkpointread that file into an emptyif letwhose bodywas a comment admitting nothing happened.
candle keeps
first_moment/second_momentin a privateVarAdamWwith no accessor, sohonouring the claim means writing and maintaining our own optimizer. Not worth it for a CPU
playground with short runs, so the claim goes instead: the config field, the
optimizer_step_*.jsonfile, the emptyif let, and the README line are removed. Whatresume does restore — weights, step counter, LR schedule position — is now documented,
along with the fact that Adam restarts cold and the loss briefly rises.
Also
save_checkpointfell back to the literal name"unknown"when the parameter and namelists disagreed in length. That collides in the safetensors map and silently drops every
parameter after the first. It now errors.
Verification
The check that matters is continuity across a resume. Last loss before: 5.0751 at step
40. First after: 5.1103 at step 45, with the learning rate picking up at the right point
on the cosine schedule. A cold start would have been back near 10.8, so the weights
genuinely restored.
New tests: a checkpoint round trip asserting every parameter matches after save and load,
and a check that the parameter and name lists agree in length and carry no duplicates —
the positional pairing is only safe while both hold.