Skip to content

Commit 41adfd0

Browse files
Bug Fix: Resuming Twice Resets the Dataloader (#8295)
* re-sync state_dict after resume * num workers test
1 parent ad2d853 commit 41adfd0

2 files changed

Lines changed: 37 additions & 0 deletions

File tree

src/datasets/iterable_dataset.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2712,6 +2712,8 @@ def _iter_pytorch(self):
27122712
}
27132713
if self._starting_state_dict and self.epoch == self._starting_state_dict["epoch"]:
27142714
ex_iterable.load_state_dict(self._starting_state_dict["examples_iterable"])
2715+
# re-point at the live ex_iterable state so progress tracking
2716+
self._state_dict["examples_iterable"] = ex_iterable._state_dict
27152717

27162718
if self._formatting and (ex_iterable.iter_arrow or self._formatting.is_table):
27172719
formatter = get_formatter(self._formatting.format_type, features=self.features)
@@ -2796,6 +2798,8 @@ def _prepare_ex_iterable_for_iteration(
27962798
}
27972799
if self._starting_state_dict and self.epoch == self._starting_state_dict["epoch"]:
27982800
ex_iterable.load_state_dict(self._starting_state_dict["examples_iterable"])
2801+
# re-point at the live ex_iterable state so progress tracking
2802+
self._state_dict["examples_iterable"] = ex_iterable._state_dict
27992803
return ex_iterable
28002804

28012805
def __iter__(self):

tests/test_iterable_dataset.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2833,6 +2833,39 @@ def test_resume_dataloader(dataset: IterableDataset):
28332833
assert remaining == list(dl)
28342834

28352835

2836+
@require_torchdata_stateful_dataloader
2837+
@pytest.mark.parametrize("num_workers", [0, 1, 2])
2838+
def test_resume_dataloader_twice(num_workers):
2839+
from torchdata.stateful_dataloader import StatefulDataLoader
2840+
2841+
ex_iterable = ExamplesIterable(generate_examples_fn, {"filepaths": [f"file{i}.txt" for i in range(4)]})
2842+
dataset = IterableDataset(ex_iterable)
2843+
2844+
def make_dataloader():
2845+
return StatefulDataLoader(dataset, batch_size=None, num_workers=num_workers)
2846+
2847+
all_examples = list(make_dataloader())
2848+
2849+
# consume 2 examples, then checkpoint #1
2850+
dl = make_dataloader()
2851+
it = iter(dl)
2852+
consumed = [next(it) for _ in range(2)]
2853+
state_1 = dl.state_dict()
2854+
2855+
# resume from #1, consume 2 more, then checkpoint #2 (taken from a resumed loader)
2856+
dl = make_dataloader()
2857+
dl.load_state_dict(state_1)
2858+
it = iter(dl)
2859+
consumed += [next(it) for _ in range(2)]
2860+
state_2 = dl.state_dict()
2861+
2862+
# resuming from #2 must continue from where it left off, not restart from the beginning
2863+
dl = make_dataloader()
2864+
dl.load_state_dict(state_2)
2865+
remainder = list(dl)
2866+
assert consumed + remainder == all_examples
2867+
2868+
28362869
@pytest.mark.parametrize("num_shards", [1, 2, 3, 7])
28372870
def test_iterable_dataset_batch(num_shards: int):
28382871
# Create a simple IterableDataset

0 commit comments

Comments
 (0)