fix(checkpoint): preserve tied lm_head on resume#2511
Merged
Conversation
b47a75b to
9920aa0
Compare
Contributor
Author
|
/ok to test 9920aa0 |
0a63f04 to
fca98ed
Compare
Contributor
Author
|
/ok to test fca98ed |
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
…d-resume Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Contributor
Author
|
/ok to test dbeb5c8 |
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Contributor
Author
|
/ok to test 50f781e |
Contributor
|
/claude review |
Contributor
|
/ok to test 406d593 |
akoumpa
approved these changes
Jun 15, 2026
Contributor
Contributor
|
FMing; codecov is hang in status report. |
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 ?
Fix tied-LM-head checkpoint/resume and sharded-training behavior by making
lm_head.weightactually alias the input embedding weight when the model config requests tied word embeddings, and by only omittinglm_head.weightfrom checkpoints when that alias is real.Bug Details
This is a checkpoint and model-state correctness bug for tied word embeddings.
For models with
config.tie_word_embeddings=true, AutoModel treatedlm_head.weightas redundant and omitted it from the saved checkpoint state. That is only safe whenlm_head.weightand the input embedding weight actually share storage. In the failing Llama pretraining reproduction, the model was built from config on meta tensors and materialized/initialized later, after__init__had already run. The config claimed tied embeddings, but the resident tensors were not physically tied at checkpoint-save time.On resume, the checkpoint loader reconstructed the missing
lm_head.weightfromembed_tokens.weight. Because the trainedlm_head.weighthad diverged as an untied parameter before save, resume silently changed the model state and produced a large first-step loss spike.The original confirmed reproduction is Llama 3.2 1B from-config pretraining with
tie_word_embeddings=true. The issue is not specific to Slurm SIGTERM/enforced checkpoints: normal checkpoint resume showed the same spike.The affected area is broader than pretraining. Any LLM/VLM path can be affected when:
tie_word_embeddings=truelm_head.weightand the input embedding weightConfirmed or directly exercised cases include:
Gemma3ForConditionalGeneration, whose HF config declares tied text embeddings and whose sharded local model can need the alias re-applied after FSDP2/DCP state handlingThis PR should be a no-op for models with
tie_word_embeddings=false, intentionally shape-mismatched heads such as speculative draft heads, pipeline stages that do not own both tensors, and models that already keep the alias intact.Changelog
ensure_tied_lm_head()to re-establish a locallm_head/ input-embedding alias when the config requests tied word embeddings.tie_weights()and add a direct local assignment fallback for wrapped/sharded models where generic tying does not reach both tensors.ModelStatetied-head metadata immediately before save-time key filtering, so DCP/FSDP alias normalization cannot leave a stalehas_local_tied_lm_head=falseand accidentally persist duplicatelm_head.weight.lm_head.weight.tie_weights()support for the custom Llama causal LM implementation.Before your PR is "Ready for review"
Pre checks:
Documentation note: this updates contributor/model-onboarding guidance rather than user-facing docs because there is no new user API or config field.
Validation:
python -m pytest tests/unit_tests/utils/test_checkpoint_utils.py tests/unit_tests/checkpoint/test_checkpointing.py tests/unit_tests/models/llama/test_llama_tied_weights_cpu.py -qpassed with111 passed, 2 skipped.ruff format --checkandruff checkon the touched checkpoint files/tests passed.ModelStateomittedlm_head.weight, optimizer state stayed undermodel.language_model.embed_tokens.weight, restored loss matched source loss, and the restored model remained tied.main: container run ofpython -m pytest tests/unit_tests/utils/test_checkpoint_utils.py tests/unit_tests/checkpoint/test_checkpointing.py tests/unit_tests/models/llama/test_llama_tied_weights_cpu.py -qpassed with109 passed, 2 skipped.source work/runs/_shared/env.sh && uv run --no-sync pytest tests/unit_tests/checkpoint/test_checkpointing.py tests/unit_tests/models/llama/test_llama_tied_weights_cpu.py -qpytest tests/unit_tests/utils/test_checkpoint_utils.py -qin the Automodel container:11 passedruff format/ruff checkon the touched checkpoint, infrastructure, model, skill, and test filesensure_tied_lm_head()Additional Information