Skip to content

Commit fecae65

Browse files
committed
feat(data): expose shuffle in DataloaderConfig
Signed-off-by: Hristo Filaretov <hfilaretov@nvidia.com>
1 parent 2061c08 commit fecae65

6 files changed

Lines changed: 35 additions & 0 deletions

File tree

‎src/megatron/bridge/data/base.py‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ class DataloaderConfig:
4343
drop_last: bool = True
4444
"""Whether dataloaders drop the last incomplete batch."""
4545

46+
shuffle: bool = True
47+
"""Whether the global-batch sampler used by ``dataloader_type="batch"`` reshuffles samples each epoch."""
48+
4649
persistent_workers: bool = True
4750
"""Whether dataloader workers persist between iterations."""
4851

‎src/megatron/bridge/data/loaders.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ def worker_init_fn(_):
334334
global_batch_size=cfg.train.global_batch_size,
335335
drop_last=drop_last,
336336
seed=sampler_seed,
337+
shuffle=cfg.dataset.shuffle,
337338
)
338339
eval_gbs = (
339340
cfg.validation.eval_global_batch_size
@@ -361,6 +362,7 @@ def worker_init_fn(_):
361362
data_parallel_size=eval_dp_size,
362363
global_batch_size=eval_gbs,
363364
seed=sampler_seed,
365+
shuffle=cfg.dataset.shuffle,
364366
)
365367
elif cfg.validation.eval_iters > 0:
366368
val_dataloader_type = "cyclic" if isinstance(cfg.dataset, GPTDatasetConfig) else cfg.dataset.dataloader_type
@@ -379,6 +381,7 @@ def worker_init_fn(_):
379381
data_parallel_size=eval_dp_size,
380382
global_batch_size=eval_gbs,
381383
seed=sampler_seed,
384+
shuffle=cfg.dataset.shuffle,
382385
)
383386

384387
if cfg.validation.eval_iters > 0:
@@ -397,6 +400,7 @@ def worker_init_fn(_):
397400
data_parallel_size=eval_dp_size,
398401
global_batch_size=eval_gbs,
399402
seed=sampler_seed,
403+
shuffle=cfg.dataset.shuffle,
400404
)
401405

402406
# Flags to know if we need to do training/validation/testing.

‎src/megatron/bridge/data/samplers.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def build_pretraining_data_loader(
2626
drop_last: Optional[bool] = True,
2727
global_batch_size: Optional[int] = None,
2828
seed: int | None = None,
29+
shuffle: bool = True,
2930
) -> Optional[DataLoader]:
3031
"""Build a dataloader for pretraining.
3132
@@ -53,6 +54,8 @@ def build_pretraining_data_loader(
5354
seed: Explicit shuffle seed for the global-batch sampler. Supplying the
5455
dataset seed keeps pipeline stages on the same sample order even
5556
though their model RNG seeds differ.
57+
shuffle: Whether the global-batch sampler reshuffles samples each epoch.
58+
Only used when dataloader_type is 'batch'.
5659
5760
Returns:
5861
A PyTorch DataLoader instance, or the dataset itself if dataloader_type is
@@ -101,6 +104,7 @@ def build_pretraining_data_loader(
101104
data_parallel_size=data_parallel_size,
102105
drop_last=drop_last,
103106
pad_samples_to_global_batch_size=not drop_last,
107+
shuffle=shuffle,
104108
seed=seed,
105109
)
106110
elif dataloader_type == "external":

‎tests/functional_tests/test_groups/data/test_loaders.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ def test_build_train_valid_test_data_loaders_uses_eval_dp_group(
320320
dataset_root="/tmp/dataset",
321321
seq_length=512,
322322
seed=4321,
323+
shuffle=False,
323324
num_workers=0,
324325
persistent_workers=False,
325326
)
@@ -355,6 +356,9 @@ def test_build_train_valid_test_data_loaders_uses_eval_dp_group(
355356
assert train_call.kwargs["seed"] == expected_seed
356357
assert valid_call.kwargs["seed"] == expected_seed
357358
assert test_call.kwargs["seed"] == expected_seed
359+
assert train_call.kwargs["shuffle"] is cfg.dataset.shuffle
360+
assert valid_call.kwargs["shuffle"] is cfg.dataset.shuffle
361+
assert test_call.kwargs["shuffle"] is cfg.dataset.shuffle
358362

359363
@mock.patch("torch.distributed.broadcast")
360364
@mock.patch("torch.distributed.get_world_size", return_value=1)

‎tests/functional_tests/test_groups/data/test_samplers.py‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ def test_batch_sampler_initialization(self):
202202
assert sampler.micro_batch_size == 4
203203
assert sampler._global_batch_size == 16
204204
assert sampler.data_parallel_size == 2
205+
assert sampler.shuffle is True
205206

206207
def test_batch_sampler_length(self):
207208
"""Test length calculation for batch sampler.
@@ -845,6 +846,23 @@ def mock_dataloader():
845846
class TestBatchDataloaderIntegration:
846847
"""Integration tests for batch dataloader type."""
847848

849+
def test_build_batch_dataloader_propagates_shuffle(self):
850+
"""The loader builder must pass shuffle through to the batch sampler."""
851+
dataloader = build_pretraining_data_loader(
852+
dataset=list(range(16)),
853+
consumed_samples=0,
854+
dataloader_type="batch",
855+
micro_batch_size=1,
856+
num_workers=0,
857+
data_sharding=False,
858+
global_batch_size=4,
859+
seed=1234,
860+
shuffle=False,
861+
)
862+
863+
assert dataloader.batch_sampler.shuffle is False
864+
assert next(iter(dataloader.batch_sampler)) == [0, 1, 2, 3]
865+
848866
def test_build_batch_dataloader_explicit_seed_is_independent_of_model_rng(self):
849867
"""Pipeline-stage model seeds must not change the fine-tuning sample order."""
850868
import torch

‎tests/unit_tests/data/builders/test_gpt_sft_config.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ def test_config_round_trip_is_declarative_and_serializable(tmp_path):
5555
hf_output_root=str(tmp_path),
5656
hf_validation_proportion=0.1,
5757
seed=5678,
58+
shuffle=False,
5859
enable_offline_packing=True,
5960
offline_packing_specs=specs,
6061
do_test=False,
@@ -68,6 +69,7 @@ def test_config_round_trip_is_declarative_and_serializable(tmp_path):
6869
assert restored.hf_dataset.dataset_name == "squad"
6970
assert restored.offline_packing_specs.packed_sequence_size == 128
7071
assert isinstance(restored.preprocessing, PromptCompletionSFTPreprocessingConfig)
72+
assert restored.shuffle is False
7173
assert "tokenizer" not in serialized
7274

7375

0 commit comments

Comments
 (0)