Bug description
Dataloader restarts from scratch after resuming twice (upstream datasets bug)
This is not a bug in torchtitan. It originates in IterableDataset from Hugging Facedatasets, but it affects torchtitan because torchtitan relies on IterableDataset for streaming data.
The bug
After a resume, IterableDataset stops tracking its own state. Concretely, load_state_dict() calls _init_state_dict(), which rebinds the example-iterable's _state_dict to a fresh object. The outer IterableDataset._state_dict["examples_iterable"] still points at the original, now stale, zero-initialized dict. During iteration the example-iterable mutates the live dict, while state_dict() keeps deep-copying the stale one, so the reported position stays frozen at zero.
The practical consequence shows up on the second consecutive resume of a training run:
- The original run tracks state correctly and writes a healthy checkpoint.
- Resuming from it reads from the right place, but every checkpoint it writes contains a stale, zero-initialized dataloader
state_dict.
- Resuming from that checkpoint restarts the data stream from the very beginning.
Full description: huggingface/datasets#8308
Affected versions
I believe that the regression was introduced in datasets==5.0.0. The rebinding _init_state_dict() call was added to the base load_state_dict in that release. Every release <= 4.8.5 (including 3.6.0) should be unaffected — those versions mutate the state dict in place and never break the reference.
The datasets fix
I authored a fix that re-links the live state after the resume load, at both IterableDataset resume sites. It has been merged on datasets main: huggingface/datasets#8295
Unfortunately, the fix is not yet in any published datasets release, so pip install -U datasets does not resolve the issue today.
Proposed workarounds
Until a datasets release ships the fix, any of the following work. Listed in the order I'd recommend for torchtitan:
-
Pin datasets < 5.0.0. Cleanest option if torchtitan's other requirements tolerate it, no patch to maintain and no dependency on a moving branch. (Worth confirming against torchtitan's current datasets floor; if something already requires >= 5.0.0, this is off the table.)
-
Pin the merged upstream commit. Prefer the merge commit SHA over @main for reproducible builds, since main drifts and pip/uv cache VCS installs aggressively:
# pyproject.toml
[project]
dependencies = [
"datasets @ git+https://github.com/huggingface/datasets.git@<merge-commit-sha>",
]
-
Temporary monkey-patch of IterableDataset. Good stopgap that keeps the released datasets pin intact. I have a tested patch and am happy to open it as an interim guard to be removed once a fixed release lands. Let me know if you'd like it.
Happy to open a PR for either.
Hope this helps.
Versions
torch == 2.14.0.dev20260612+cu126
datasets == 5.0.0
Bug description
Dataloader restarts from scratch after resuming twice (upstream
datasetsbug)This is not a bug in torchtitan. It originates in
IterableDatasetfrom Hugging Facedatasets, but it affects torchtitan because torchtitan relies onIterableDatasetfor streaming data.The bug
After a resume,
IterableDatasetstops tracking its own state. Concretely,load_state_dict()calls_init_state_dict(), which rebinds the example-iterable's_state_dictto a fresh object. The outerIterableDataset._state_dict["examples_iterable"]still points at the original, now stale, zero-initialized dict. During iteration the example-iterable mutates the live dict, whilestate_dict()keeps deep-copying the stale one, so the reported position stays frozen at zero.The practical consequence shows up on the second consecutive resume of a training run:
state_dict.Full description: huggingface/datasets#8308
Affected versions
I believe that the regression was introduced in
datasets==5.0.0. The rebinding_init_state_dict()call was added to the baseload_state_dictin that release. Every release<= 4.8.5(including 3.6.0) should be unaffected — those versions mutate the state dict in place and never break the reference.The
datasetsfixI authored a fix that re-links the live state after the resume load, at both
IterableDatasetresume sites. It has been merged ondatasetsmain: huggingface/datasets#8295Unfortunately, the fix is not yet in any published
datasetsrelease, sopip install -U datasetsdoes not resolve the issue today.Proposed workarounds
Until a
datasetsrelease ships the fix, any of the following work. Listed in the order I'd recommend for torchtitan:Pin
datasets < 5.0.0. Cleanest option if torchtitan's other requirements tolerate it, no patch to maintain and no dependency on a moving branch. (Worth confirming against torchtitan's currentdatasetsfloor; if something already requires>= 5.0.0, this is off the table.)Pin the merged upstream commit. Prefer the merge commit SHA over
@mainfor reproducible builds, sincemaindrifts and pip/uv cache VCS installs aggressively:Temporary monkey-patch of
IterableDataset. Good stopgap that keeps the releaseddatasetspin intact. I have a tested patch and am happy to open it as an interim guard to be removed once a fixed release lands. Let me know if you'd like it.Happy to open a PR for either.
Hope this helps.
Versions