core.datasets.data_schedule_utils#
Module Contents#
Functions#
Unpacks the packed samples into a list of sub-samples. Since each sub-sample may be routed to different DPxCP ranks, we unpack the sample here to avoid unnecessarily transferring the entire packed sample. |
|
Gathers the sequence lengths of all subsamples from all DP ranks and calculates global IDs. |
|
Pack multiple samples into a single packed sample. |
|
Broadcast a tensor from src_rank to all ranks in the group. |
|
Broadcast num_micro_batches, seqlen_sum_this_global_batch, seqlen_squared_sum_this_global_batch and metadata to middle PP stages. Before this broadcast, the new_samples on middle PP stages are None, after this broadcast, the new_samples on middle PP stages contain the metadata but without tokens, labels, loss_mask, position_ids. |
|
Broadcast scalar values from rank 0 to all ranks in the group. |
|
Handle virtual pipeline parallelism. |
|
Reroutes the sub-samples to the correct rank after scheduling. |
|
Build packed samples for each microbatch. |
|
Get the batch and global sequence lengths. Each DP rank loads the same number of sequences, so we need to gather the sequence lengths from all ranks then we can schedule the sequences into groups. |
API#
- core.datasets.data_schedule_utils._unpack_batch(
- batch: List[Dict[str, torch.Tensor]],
Unpacks the packed samples into a list of sub-samples. Since each sub-sample may be routed to different DPxCP ranks, we unpack the sample here to avoid unnecessarily transferring the entire packed sample.
Two mutually exclusive input shapes are accepted, and every sample in
batchmust use the same one:Pre-packed (e.g. :class:
SFTDataset): each sample carries acu_seqlenstensor and the tokens of multiple sub-samples concatenated together. We slice them apart and synthesizeoriginal_seq_len/padded_seq_lenfrom the cu_seqlens deltas.Already unpacked (e.g. :class:
VarlenDataset): each sample is a single sub-sample that already carriespadded_seq_len(and usuallyoriginal_seq_len). We just normalize the leading batch dimension introduced by the default collate_fn and return as-is.
The shape is decided once for the whole batch and asserted per sample, so a dataset that emits both keys cannot silently bypass the
cu_seqlensslicing below.
- core.datasets.data_schedule_utils._get_global_seqlens_and_ids(subsample_seqlens: torch.Tensor, dp_group)#
Gathers the sequence lengths of all subsamples from all DP ranks and calculates global IDs.
- core.datasets.data_schedule_utils._pack_sequences(
- samples: List,
- padded_lengths: torch.Tensor,
- original_lengths: torch.Tensor,
- dev: torch.device,
Pack multiple samples into a single packed sample.
- core.datasets.data_schedule_utils.broadcast_tensor(item, src_rank, group) None#
Broadcast a tensor from src_rank to all ranks in the group.
- core.datasets.data_schedule_utils.broadcast_to_pp_group(
- new_samples,
- num_micro_batches,
- seqlen_sum_this_global_batch,
- seqlen_squared_sum_this_global_batch,
- pp_group,
- dev,
Broadcast num_micro_batches, seqlen_sum_this_global_batch, seqlen_squared_sum_this_global_batch and metadata to middle PP stages. Before this broadcast, the new_samples on middle PP stages are None, after this broadcast, the new_samples on middle PP stages contain the metadata but without tokens, labels, loss_mask, position_ids.
Who needs what:
PP rank 0 and the last PP rank both own a data iterator (only TP rank 0 on the first and last PP stage does), so both run the whole schedule -> reroute -> pack pipeline on the same input samples and independently end up with complete
new_samples: tokens, labels, loss_mask, position_ids and the packing metadata. Neither takes anything from this broadcast; the last stage in particular must keep its own labels / loss_mask.Middle PP stages have no data iterator, so
new_samplesis None on entry. They only need the packing metadata (max_seqlen / cu_seqlens / cu_seqlens_padded) to rebuild the packed-sequence params, never the token tensors.
The last PP rank still takes part in the transfer because
torch.distributed.broadcastis a collective overpp_group: every member has to call it or the group deadlocks. It therefore receives the payload and drops it, which is what thepp_group.rank() != pp_group.size() - 1guard below implements. Filtering it out of the transfer itself would require a separate “first + middle” process group, which is not worth an extra process group for a payload of a few hundred bytes per global batch.
- core.datasets.data_schedule_utils.broadcast_scalars(
- values: List,
- group,
- dev,
- dtype=torch.float32,
Broadcast scalar values from rank 0 to all ranks in the group.
- Parameters:
values – List of scalar values to broadcast (only used on rank 0).
group – The process group to broadcast within.
dev – The device to use for the tensor.
dtype – The data type for the tensor.
- Returns:
List of broadcasted values.
- core.datasets.data_schedule_utils.create_data_iterator(new_samples, pp_group, tp_group, config)#
Handle virtual pipeline parallelism.
- core.datasets.data_schedule_utils.reroute_samples_to_dcp_ranks(
- batch,
- global_ids_this_rank,
- global_id_seqlens,
- sample_id_groups,
- offsets,
- dp_group,
- tp_group,
- dp_cp_group,
- total_dcp_gpus,
Reroutes the sub-samples to the correct rank after scheduling.
For each key in the batch dict, we perform an all-to-all communication to transfer the data to the correct ranks.
- core.datasets.data_schedule_utils.build_packed_microbatches(
- grouped_samples: List[List[Dict[str, torch.Tensor]]],
- dev: torch.device,
Build packed samples for each microbatch.
- core.datasets.data_schedule_utils.get_batch_and_global_seqlens(
- data_iterator,
- num_microbatches,
- dp_group,
Get the batch and global sequence lengths. Each DP rank loads the same number of sequences, so we need to gather the sequence lengths from all ranks then we can schedule the sequences into groups.
- Parameters:
data_iterator – The data iterator.
num_microbatches – The number of microbatches.
dp_group – The data parallel group.
- Returns:
The sub-samples pulled from this rank’s
data_iteratorovernum_microbatchessteps, flattened and unpacked (see :func:_unpack_batch). Every dict carriestokens/labels/loss_mask/position_idsplus theoriginal_seq_lenandpadded_seq_lenscalars used for scheduling. global_id_seqlens (List[Tuple[int, int]]):(global_id, padded_seq_len)for every sub-sample in the DP group, ordered by DP rank and then by local index. Identical on all ranks; this is the scheduler’s input. global_ids_this_rank (torch.Tensor): int32 CUDA tensor holding the global IDs of the sub-samples loaded by this rank, i.e.batch[i]has global IDglobal_ids_this_rank[i]. offsets (torch.Tensor): int32 CPU tensor of shape[dp_size + 1]with the exclusive prefix sum of the per-rank sub-sample counts, so DP rankrowns global IDsoffsets[r]:offsets[r + 1]. Used by :func:reroute_samples_to_dcp_ranksto map a global ID back to its source rank. seqlens_gathered (List[int]): Padded sequence length of every sub-sample in the DP group, indexed by global ID (seqlens_gathered[gid]equalsglobal_id_seqlens[gid][1]). Handy for global-batch token counts such as the FLOPs accounting.- Return type:
batch (List[Dict[str, torch.Tensor]])