Data Loading
Concepts
The DataProvider is the factory you supply to the train/eval loop — exactly like ModelProvider or
OptimizerProvider. Given the run context, it composes and returns a MicrobatchPackStream: a
Stateful iterable that yields microbatch packs and reports its length via a total_steps property.
- A pack is one step's worth of data: a sequence of microbatches.
len(pack)is the number of microbatches within that step (the gradient-accumulation factor) and may vary from step to step. The loop moves each pack to the device and hands it to the task operator. total_stepsis the number of steps the stream will yield, orNonewhen that cannot be known ahead of time (streaming / data-dependent batching).JobScheduleuses it to resolve the job duration, falling back toJobScheduleConfig.total_stepswhen it isNone.- The stream is the single checkpoint boundary for the data: it saves and restores its own position (per data-parallel rank) so resumption is exact.
There are two ways to obtain a DataProvider: use the shipped AutoDataProvider for the common case, or
write your own for full control.
Using AutoDataProvider
AutoDataProvider wires the default stack for
you. You supply only the two non-serializable pieces — a dataset_factory and a collator — plus an
AutoDataConfig for the serializable knobs (global_batch_size, microbatch_size,
shard_indexing_mode, drop_last, and DataLoader settings such as shuffle / num_workers /
pin_memory / prefetch_factor).
It shards the dataset across data-parallel ranks for you, builds the loader, derives the gradient-accumulation factor, and returns the stream — so your factory returns the unsharded dataset.
- The
dataset_factoryreceives theDistributedContext, so it can guard data preparation (e.g. withdist_context.main_process_first()so rank 0 populates the cache before the others read it). - The
collatorcollates a list of samples into one microbatch.
Because the batch sizes are known, the resulting stream is length-aware (total_steps is populated), so
JobSchedule derives the job duration without you setting JobScheduleConfig.total_steps.
Writing a custom DataProvider
A custom provider composes the same default stack by hand, which is two layers (both in
d9d.dataset.batch_iterator):
- A loader — any
DataLoaderProtocol: aStateful,Sizediterable of single collated microbatches. torchdata'sStatefulDataLoadersatisfies it directly. - A packer —
FixedCountMicrobatchPacker(microbatches_per_step=k)groupskmicrobatches into each pack, reproducing gradient accumulation (drop_lastcontrols whether a short trailing pack is dropped — training drops it, evaluation keeps it). The accumulation factorkis derived with the helpernum_microbatches_for_global_batch.
Unlike AutoDataProvider, you own the data-parallel sharding: shard the dataset yourself (e.g. with
shard_dataset_data_parallel) before building
the loader. See the Dataset Utilities documentation.
API reference
d9d.loop.control.data_provider
DataProvider
Bases: Protocol
Protocol that allows users to define how the data pipeline is built.
A DataProvider is the factory the user supplies to the train/eval loop, exactly like
ModelProvider or OptimizerProvider. Given the run context, it composes and returns a
MicrobatchPackStream.
The user is responsible for sharding the dataset across data-parallel ranks (e.g. with
d9d.dataset.shard_dataset_data_parallel) inside the provider.
__call__(context)
Builds the microbatch pack stream for the job.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
InitializeDataProviderContext
|
Context for this operation. |
required |
Returns:
| Type | Description |
|---|---|
MicrobatchPackStream
|
The microbatch pack stream the loop will drive. |
InitializeDataProviderContext
dataclass
Context data required to initialize a data provider.
Attributes:
| Name | Type | Description |
|---|---|---|
dist_context |
DistributedContext
|
The distributed context containing rank and world size information. |
d9d.loop.auto.auto_data
DatasetFactory = Callable[[DistributedContext], Dataset]
module-attribute
A callable that builds the (unsharded) dataset, given the distributed context.
It receives the context so it can guard data preparation (e.g. with dist_context.main_process_first()).
AutoDataConfig
Bases: BaseModel
Configuration for the default data pipeline.
Attributes:
| Name | Type | Description |
|---|---|---|
global_batch_size |
int
|
The total effective batch size across all replicas and accumulation. |
microbatch_size |
int
|
The number of samples in a single microbatch on a single rank. |
shard_indexing_mode |
ShardIndexingMode
|
The dataset sharding strategy. |
shuffle |
bool
|
Whether to reshuffle the data every epoch. |
drop_last |
bool
|
Whether to drop the trailing incomplete microbatch and pack (set False for evaluation). |
num_workers |
int
|
The number of subprocesses to use for data loading. |
pin_memory |
bool
|
Whether to copy tensors into CUDA pinned memory before returning them. |
persistent_workers |
bool
|
Whether to keep worker processes alive between epochs. |
prefetch_factor |
int | None
|
The number of batches each worker prefetches ahead. |
timeout |
float
|
The timeout in seconds for collecting a batch from workers. |
AutoDataProvider
Bases: DataProvider
DataProvider that wires the default stack: shard the dataset, load microbatches, pack them per step.
It shards the dataset across data-parallel ranks, wraps it in a stateful loader at the microbatch size,
derives the gradient-accumulation factor from the global batch size, and groups the microbatches with a
FixedCountMicrobatchPacker. Users who need a non-default stack should write their own DataProvider.
__init__(dataset_factory, collator, config)
Constructs the AutoDataProvider object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dataset_factory
|
DatasetFactory
|
Builds the unsharded dataset given the distributed context. |
required |
collator
|
CollateFn
|
Collates individual samples into a microbatch. |
required |
config
|
AutoDataConfig
|
The serializable settings for the default stack. |
required |
d9d.dataset.batch_iterator
Composable building blocks for the batch-iterator stack.
FixedCountMicrobatchPacker
Bases: MicrobatchPackStream
The default MicrobatchPackStream that groups microbatches_per_step microbatches from a loader per pack.
Keeping a short trailing pack (drop_last=False) is only consistent across ranks when every rank sees the
same number of microbatches (e.g. the dataset was sharded with pad_to_equal_size_across_shards).
Its total_steps is derived from the loader's length, and it delegates its state to the loader
(the checkpoint boundary).
total_steps
property
Returns the number of packs (steps) this packer yields.
Returns:
| Type | Description |
|---|---|
int | None
|
The pack count, including a trailing short pack unless |
__init__(loader, microbatches_per_step, drop_last=True)
Constructs a FixedCountMicrobatchPacker object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
loader
|
DataLoaderProtocol
|
The microbatch stream to group. |
required |
microbatches_per_step
|
int
|
The number of microbatches in each pack. |
required |
drop_last
|
bool
|
Whether to drop the trailing incomplete pack instead of yielding it short. |
True
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
__iter__()
Iterates the loader, grouping microbatches into packs.
Yields:
| Type | Description |
|---|---|
MicrobatchPack
|
A full pack, or a shorter trailing pack when |
num_microbatches_for_global_batch(dist_context, global_batch_size, microbatch_size)
Computes the number of microbatches per step required to reach a target global batch size.
The global batch is spread across the data-parallel ranks, and each rank processes microbatch_size samples
per microbatch, so the number of microbatches a single rank must process per optimizer step is
"global_batch_size / (dp_size * microbatch_size)".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dist_context
|
DistributedContext
|
The distributed context. |
required |
global_batch_size
|
int
|
The total effective batch size across all replicas and accumulation. |
required |
microbatch_size
|
int
|
The number of samples in a single microbatch on a single rank. |
required |
Returns:
| Type | Description |
|---|---|
int
|
The number of microbatches per step (the gradient-accumulation factor). |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the global batch size is not divisible by the product of the data-parallel cardinality and the microbatch size. |