Datasets
About
The d9d.dataset package provides PyTorch Dataset wrappers and helpers for distributed training. It covers length-based bucketing, data-parallel sharding, padding and token pooling masks.
Why d9d Does Not Wrap Datasets Automatically
d9d provides explicit wrappers that you compose yourself. It does not inject samplers or wrap datasets behind your back, as some other frameworks do.
- Order of composition: A data pipeline behaves differently depending on the order of its wrappers. For example, bucketing before sharding is not the same as sharding before bucketing. When you stack the wrappers yourself, you control this order.
- Per-dataset configuration: Datasets have different physical limits. A dataset on network storage can need contiguous reads (
ShardIndexingMode.chunked), while an in-memory dataset can use round-robin access (ShardIndexingMode.sequential). Explicit wrappers expose these options instead of hiding them in global trainer arguments.
Bucketing
In sequence processing, the items of a batch often have different lengths. With random sampling, every batch is padded to its longest sequence, so compute is spent on padding tokens.
BufferSortedDataset reads a buffer of items, sorts it by a sort key (usually the length) and splits it into packs. Items in one pack, e.g. one microbatch, have similar lengths, which reduces padding. It then shuffles the packs and the items within each pack, so the data order is not strictly sorted.
The underlying dataset must implement DatasetImplementingSortKeyProtocol, i.e. it must have a sort_key(index) method.
Sharding
With data parallelism, each GPU processes a subset of the data. ShardedDataset is a deterministic view of one shard of the data, selected by the shard index (usually the data-parallel rank).
It supports:
- Sequential sharding: Round-robin distribution (
0, 4, 8, ...for rank 0 of 4). - Chunked sharding: Contiguous blocks (
0, 1, 2, ...for rank 0). - Optional padding: All shards get the same length by repeating the last item. Without it, ranks with fewer items finish early, and the other ranks hang in collectives.
shard_dataset_data_parallel builds a ShardedDataset for the data-parallel dimension of a DistributedContext.
A ShardedDataset must be restored from a checkpoint with the same number of shards.
Padding
Variable-length sequences must be padded to the same length before they can be stacked into a batch. pad_stack_1d pads and stacks 1D tensors. Use it to write a collate_fn.
Token Pooling
token_pooling_mask_from_attention_mask builds a mask of the tokens to pool from an attention mask. TokenPoolingType selects the first token, the last non-padding token or all non-padding tokens. The last mode assumes right padding.
Microbatch Packing
FixedCountMicrobatchPacker, PinMemoryMicrobatchPackStream and num_microbatches_for_global_batch build the stream of microbatch packs that the training loop consumes. See Data Loading for how to use them.
Usage
Bucketing
Sharding for Data Parallelism
Manual Sharding
Padding
API Reference
d9d.dataset
Dataset wrappers and data utilities for distributed training.
BufferSortedDataset
Bases: Dataset[_T_co], Stateful
Dataset wrapper that serves items sorted within buffers, with local shuffling.
Items of similar length end up in the same pack, which reduces padding in variable-length training. The shuffling keeps enough randomness in the order of updates.
Algorithm:
- Select a range of
buffer_sizeindices. - Build sort keys:
(base_dataset.sort_key(index), random_tie_breaker). - Sort the indices by these keys.
- Split the sorted list into packs of
pack_sizeitems. - Shuffle the order of the packs.
- Shuffle the items within each pack.
- Flatten and serve.
__init__(base_dataset, buffer_size, pack_size, init_seed=None)
Constructs the BufferSortedDataset object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_dataset
|
DatasetImplementingSortKeyProtocol[_T_co]
|
The underlying dataset. |
required |
buffer_size
|
int
|
The number of items sorted together. |
required |
pack_size
|
int
|
The size of a group of similar items, usually the batch or microbatch size. |
required |
init_seed
|
int | None
|
Seed for the random number generator. |
None
|
DatasetImplementingSortKeyProtocol
Bases: Protocol[_T_co]
Protocol for datasets that return a sort key for an item without loading it.
It is typically used for length-based bucketing, where the dataset exposes the length of an item.
__getitem__(item)
Returns the item at the given index.
__len__()
Returns the total number of items in the dataset.
FixedCountMicrobatchPacker
Bases: MicrobatchPackStream
Microbatch pack stream that groups the microbatches of a loader into packs of microbatches_per_step.
It is the default MicrobatchPackStream. A short trailing pack (drop_last=False) is consistent across
ranks only when every rank sees the same number of microbatches, e.g. when 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
The number of packs (steps) this packer yields.
It includes a trailing short pack unless drop_last is set.
__init__(loader, microbatches_per_step, drop_last=True)
Constructs the 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 |
PaddingSide1D
Bases: StrEnum
Side on which 1D sequences are padded.
Attributes:
| Name | Type | Description |
|---|---|---|
left |
Pad on the left side. |
|
right |
Pad on the right side. |
PinMemoryMicrobatchPackStream
Bases: MicrobatchPackStream
Microbatch pack stream wrapper that copies every tensor of each pack into pinned host memory.
Pinned memory lets the loop copy packs to the device asynchronously. Unlike the pin_memory option of
torch.utils.data.DataLoader, the traversal uses d9d.core.pytree, so tensors nested in dataclasses are
pinned as well. Pinning runs in the iterating thread.
Its total_steps and state are those of the wrapped stream.
total_steps
property
The number of packs (steps) the wrapped stream yields, or None if it is unknown.
__init__(inner)
Constructs the PinMemoryMicrobatchPackStream object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inner
|
MicrobatchPackStream
|
The wrapped stream that owns the data and its position. |
required |
__iter__()
Iterates the wrapped stream, pinning each pack.
Yields:
| Type | Description |
|---|---|
MicrobatchPack
|
The next pack with all of its tensors in pinned host memory. |
ShardIndexingMode
Bases: StrEnum
Ways to split a dataset across shards.
The examples show 14 items split across 4 shards.
Attributes:
| Name | Type | Description |
|---|---|---|
sequential |
Round-robin distribution. shard0: 0, 4, 8, 12 shard1: 1, 5, 9, 13 shard2: 2, 6, 10 shard3: 3, 7, 11 |
|
chunked |
Contiguous blocks. shard0: 0, 1, 2, 3 shard1: 4, 5, 6, 7 shard2: 8, 9, 10, 11 shard3: 12, 13 |
ShardedDataset
Bases: Dataset[_T_co], Stateful
Dataset wrapper that exposes only one shard of a dataset.
Use it for data-parallel training, where each process sees only a subset of the data. Optional padding gives all shards the same length, so no rank waits forever in a collective.
__getitem__(index)
Returns the item at an index relative to this shard.
If the index points past the end of the dataset, which happens only with padding, returns the last item of the dataset.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index
|
int
|
The index relative to this shard. |
required |
Returns:
| Type | Description |
|---|---|
_T_co
|
The data item. |
__init__(dataset, total_shards, current_shard, indexing_mode, pad_to_equal_size_across_shards)
Constructs the ShardedDataset object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dataset
|
Dataset[_T_co]
|
The underlying dataset to shard. |
required |
total_shards
|
int
|
The total number of shards, e.g. the number of data-parallel ranks. |
required |
current_shard
|
int
|
The index of the current shard, e.g. the current data-parallel rank. |
required |
indexing_mode
|
ShardIndexingMode
|
How indices are assigned to shards. |
required |
pad_to_equal_size_across_shards
|
bool
|
If |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
__len__()
Returns the number of items in this shard.
If pad_to_equal_size_across_shards is True, returns the maximum shard length.
Returns:
| Type | Description |
|---|---|
int
|
The number of items in the shard. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the indexing mode is unknown. |
TokenPoolingType
Bases: StrEnum
Supported token pooling strategies.
Attributes:
| Name | Type | Description |
|---|---|---|
first |
Selects the first token of the sequence, e.g. the |
|
last |
Selects the last non-padding token of the sequence, e.g. for decoder-only models. |
|
all |
Selects all non-padding tokens, e.g. for mean pooling. |
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 each rank processes global_batch_size / (dp_size * microbatch_size) microbatches per
optimizer step.
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 |
pad_stack_1d(items, pad_value, padding_side=PaddingSide1D.right, pad_to_multiple_of=None)
Pads 1D tensors to the same length and stacks them into a batch.
All tensors are padded to the length of the longest one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
items
|
Sequence[Tensor]
|
The 1D tensors to stack. |
required |
pad_value
|
int
|
The value used for padding. |
required |
padding_side
|
PaddingSide1D
|
The side on which to pad. |
right
|
pad_to_multiple_of
|
int | None
|
If set, the padded length is rounded up to a multiple of this value. |
None
|
Returns:
| Type | Description |
|---|---|
Tensor
|
The stacked tensor. Shape: |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
shard_dataset_data_parallel(dataset, dist_context, indexing_mode=ShardIndexingMode.sequential, pad_to_equal_size_across_shards=True)
Wraps a dataset into a ShardedDataset over the data-parallel ranks.
The shard count and index come from the "dp" dimension of the batch domain mesh. Without distributed
training, the dataset has a single shard.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dataset
|
Dataset[_T_co]
|
The source dataset to shard. |
required |
dist_context
|
DistributedContext
|
The distributed context. |
required |
indexing_mode
|
ShardIndexingMode
|
How indices are assigned to shards. |
sequential
|
pad_to_equal_size_across_shards
|
bool
|
If |
True
|
Returns:
| Type | Description |
|---|---|
Dataset[_T_co]
|
A dataset instance representing the local shard. |
token_pooling_mask_from_attention_mask(attention_mask, pooling_type)
Builds a binary mask of the tokens to pool for the given strategy.
last assumes right padding.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attention_mask
|
Tensor
|
A binary mask of valid tokens (1) and padding (0). Shape: |
required |
pooling_type
|
TokenPoolingType
|
The strategy for selecting tokens. |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
A mask with 1 at the positions to pool and 0 elsewhere. |
Tensor
|
mask. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |