Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion megatron/core/model_parallel_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class ModelParallelConfig:
can handle without overflowing the memory. Typically, a good starting point is to set this
to maximum sequence length / context parallel size.
This is used to calculate the number and length of sub-samples assigned to
each rank when using hybrid_context_parallel.
each rank when sequence_packing_scheduler is not None.
"""

hybrid_context_parallel: bool = False
Expand All @@ -124,6 +124,12 @@ class ModelParallelConfig:
Please set max_seqlen_per_dp_cp_rank when using hybrid_context_parallel.
"""

sequence_packing_scheduler: Optional[Literal['dp_balanced']] = None
"""
Scheduler for sequence packing and hybrid context parallel.
dp_balanced: DP-balanced scheduler for sequence packing.
"""

expert_model_parallel_size: int = 1
"""Distributes Moe Experts across sub data parallel dimension."""

Expand Down
34 changes: 34 additions & 0 deletions megatron/core/transformer/transformer_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3200,6 +3200,40 @@ def _scope_to_str(s):
"Disable MoE capacity/expert padding."
)

if self.sequence_packing_scheduler is not None:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't some/most of these checks be in model_parallel_config if that's where sequence_packing_scheduler is?

# Check TE version.
if not HAVE_PACKAGING:
raise ImportError(
"packaging is not installed. Please install it with `pip install packaging`."
)
# TODO: remove this after we fix the convergence issue with TE < 2.9.
if not (
is_te_min_version("2.9.0") or get_te_version() == PkgVersion("2.9.0.dev0+5b3092a")
):
raise ValueError(
"SFT sequence packing requires Transformer Engine >= 2.9.0 "
f"but got {get_te_version()} (TE < 2.9.0 may have convergence issues)."
)

# Needed for passing variable sequences between pp stages.
self.variable_seq_lengths = True

# TODO(tailaim): add support for other dispatcher types
assert self.moe_token_dispatcher_type == "alltoall", (
f"sequence_packing only supports moe_token_dispatcher_type='alltoall', "
f"got '{self.moe_token_dispatcher_type}'"
)

supported_schedulers = ['dp_balanced']
if (
self.sequence_packing_scheduler is not None
and self.sequence_packing_scheduler not in supported_schedulers
):
raise ValueError(
f"Unsupported scheduler: {self.sequence_packing_scheduler}. "
f"Available schedulers: {supported_schedulers}"
)


@dataclass
class MLATransformerConfig(TransformerConfig):
Expand Down
72 changes: 63 additions & 9 deletions megatron/training/arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -1246,13 +1246,6 @@ def validate_args(args, defaults={}):
if args.rl_use_sequence_packing:
args.consumed_train_bins = 0

# Support for variable sequence lengths across batches/microbatches.
# set it if the dataloader supports generation of variable sequence lengths
# across batches/microbatches. Due to additional communication overhead
# during pipeline parallelism, it should not be set if sequence length
# is constant during training.
args.variable_seq_lengths = False

# Iteration-based training.
# Skip these checks when skip_train is set: LR config is irrelevant.
if args.train_iters and not args.skip_train:
Expand Down Expand Up @@ -1430,6 +1423,23 @@ def validate_args(args, defaults={}):
assert args.dataloader_type == 'single', 'Hybrid context parallelism only supported with single dataloader type'
assert args.calculate_per_token_loss, 'Hybrid context parallelism must be used with --calculate-per-token-loss'

# Support for variable sequence lengths across batches/microbatches.
# set it if the dataloader supports generation of variable sequence lengths
# across batches/microbatches. Due to additional communication overhead
# during pipeline parallelism, it should not be set if sequence length
# is constant during training.
args.variable_seq_lengths = False
if args.mock_data and args.sft and args.sft_mock_dataset_config_json is None:
args.sft_mock_dataset_config_json = json.dumps(
{
"mode": "distribution",
"type": "lognormal",
"min_seq_len": args.seq_length // 2,
"max_seq_len": args.seq_length,
"mean_seq_len": args.seq_length // 4 * 3,
"lognormal_sigma": 1.1,
}
)
# disable async_tensor_model_parallel_allreduce when
# model parallel memory optimization is enabled
if (args.tensor_model_parallel_size > 1 or args.context_parallel_size > 1) \
Expand Down Expand Up @@ -1642,6 +1652,19 @@ def validate_args(args, defaults={}):
if args.ckpt_format == "fsdp_dtensor":
assert args.use_megatron_fsdp, "--ckpt-format fsdp_dtensor is only tested with Megatron FSDP."

# Packed-sequence buffer-size check. Placed after varlen scheduler
# auto-select so it validates the final resolved scheduler.
if args.sequence_packing_scheduler is not None:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can these checks be in the config dataclass post_init?

args.variable_seq_lengths = True
assert args.max_seqlen_per_dp_cp_rank is not None, (
"--max-seqlen-per-dp-cp-rank must be set when using sequence packing"
)
total_cp_ranks = args.context_parallel_size
assert total_cp_ranks * args.max_seqlen_per_dp_cp_rank >= args.seq_length, (
f'Packed sequence buffer size ({total_cp_ranks * args.max_seqlen_per_dp_cp_rank}) '
f'must be >= single sequence max length ({args.seq_length})'
)

# Data blend checks
assert args.mock_data + \
bool(args.data_path) + \
Expand Down Expand Up @@ -2336,6 +2359,9 @@ def _add_network_size_args(parser):
"gtp_weight_remat_size",
# internal/derived: controlled only via --expert-tensor-parallel-num-weight-shards
"expert_gtp_weight_remat_size",
"max_seqlen_per_dp_cp_rank",
"hybrid_context_parallel",
"sequence_packing_scheduler",
]
transformer_factory = ArgumentGroupFactory(TransformerConfig, exclude=exclude)
transformer_group = transformer_factory.build_group(parser, "transformer configuration")
Expand Down Expand Up @@ -3172,6 +3198,14 @@ def _add_distributed_args(parser):
'all layers will share the same communication type. Users can also '
'specify separated types for each layer like '
'--cp-comm-type p2p p2p a2a a2a a2a+p2p a2a+p2p')
group.add_argument('--max-seqlen-per-dp-cp-rank', type=int, default=None,
help='Maximum sequence length per CP rank. This is used to calculate the '
'number of sub-samples assigned to each CP rank when using heterogeneous context parallel.')
group.add_argument('--hybrid-context-parallel', action='store_true', default=False,
help='Enables hybrid context parallel. This is used to balance the workload '
'of each CP rank when we use packed samples with variable sequence lengths. '
'Requires --max-seqlen-per-dp-cp-rank to be set.')
group.add_argument('--sequence-packing-scheduler', type=str, default=None, choices=['dp_balanced'])
group.add_argument('--fake-process-group', action='store_true', default=False,
help='If set, initialize with fake distributed process group and all distributed communication operations will be skipped. \
This is quite useful for profiling memory usage of distributed training with just one GPU. \
Expand Down Expand Up @@ -3719,8 +3753,28 @@ def _add_kitchen_quantization_arguments(parser: argparse.ArgumentParser):
def _add_sft_args(parser):
group = parser.add_argument_group(title='sft')
group.add_argument('--sft', action="store_true", help='Megatron SFT training')
group.add_argument('--sft-tokenizer-prompt-format', type=str, default="nemotron-h-aligned",
help='SFT prompt format.')
group.add_argument(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why change the formatting here?

'--sft-tokenizer-prompt-format',
type=str,
default="nemotron-h-aligned",
help='SFT prompt format.',
)
group.add_argument(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you match the formatting of other arguments?

'--sft-mock-dataset-config-json',
type=str,
default=None,
help='This config provides the necessary information for the mock dataset. '
'Accepts either an inline JSON literal or a path to a JSON file containing '
'the same schema. You can either specify a CSV file that contains sequence lengths, '
'where each line stores the length of a sequence, for example: '
'{"mode":"file","path":"/path/to/file"}. Alternatively, you can specify a distribution '
'(currently only supporting lognormal distribution) along with the required parameters, '
'for example, {"mode":"distribution","type":"lognormal","min_seq_len":1024,'
'"max_seq_len":2048,"mean_seq_len":1536,"lognormal_sigma":1.1}, where sigma controls '
'the variability of the lognormal distribution. '
'If not specified and --mock-data is set, defaults to a lognormal distribution with '
'min_seq_len=seq_length//2, max_seq_len=seq_length, mean_seq_len=seq_length*3//4, lognormal_sigma=1.1.',
)
return parser

def _add_logits_distillation_args(parser):
Expand Down
Loading
Loading