| |
|
|
| """Megatron initialization.""" |
|
|
| import torch |
| from datetime import timedelta |
|
|
| from megatron import get_args |
| from megatron.core import mpu, tensor_parallel |
| from megatron.arguments import parse_args, validate_args |
| from megatron.checkpointing import load_args_from_checkpoint |
| from megatron.global_vars import set_global_variables |
| from megatron.initialize import _set_random_seed, _init_autoresume |
| from megatron.initialize import _compile_dependencies |
|
|
| from .arguments import validate_moe_args |
|
|
|
|
|
|
| def initialize_megatron( |
| extra_args_provider=None, |
| args_defaults={}, |
| ignore_unknown_args=False, |
| allow_no_cuda=False, |
| ): |
| """Set global variables, initialize distributed, and |
| set autoresume and random seeds. |
| `allow_no_cuda` should not be set unless using megatron for cpu only |
| data processing. In general this arg should not be set unless you know |
| what you are doing. |
| Returns a function to finalize distributed env initialization |
| (optionally, only when args.lazy_mpu_init == True) |
| """ |
| if not allow_no_cuda: |
| |
| assert torch.cuda.is_available(), "Megatron requires CUDA." |
|
|
| |
| args = parse_args(extra_args_provider, ignore_unknown_args) |
|
|
| if args.use_checkpoint_args or args_defaults.get("use_checkpoint_args", False): |
| assert args.load is not None, "--use-checkpoints-args requires --load argument" |
| load_args_from_checkpoint(args) |
|
|
| validate_args(args, args_defaults) |
| validate_moe_args(args, args_defaults) |
|
|
| |
| |
| set_global_variables(args) |
|
|
| |
| def finish_mpu_init(): |
| args = get_args() |
| |
| _initialize_distributed() |
|
|
| |
| if args.rank == 0: |
| print("> setting random seeds to {} ...".format(args.seed)) |
| _set_random_seed(args.seed, args.data_parallel_random_init) |
|
|
| args = get_args() |
| if args.lazy_mpu_init: |
| |
| args.use_cpu_initialization = True |
| |
| |
| mpu.set_tensor_model_parallel_world_size(args.tensor_model_parallel_size) |
| |
| |
| mpu.set_tensor_model_parallel_rank(args.rank) |
| return finish_mpu_init |
| else: |
| |
| finish_mpu_init() |
|
|
| |
| _init_autoresume() |
|
|
| |
| _compile_dependencies() |
|
|
| |
| return None |
|
|
| def _initialize_distributed(): |
| """Initialize torch.distributed and core model parallel.""" |
| args = get_args() |
|
|
| device_count = torch.cuda.device_count() |
| if torch.distributed.is_initialized(): |
|
|
| if args.rank == 0: |
| print( |
| "torch distributed is already initialized, " |
| "skipping initialization ...", |
| flush=True, |
| ) |
| args.rank = torch.distributed.get_rank() |
| args.world_size = torch.distributed.get_world_size() |
|
|
| else: |
|
|
| if args.rank == 0: |
| print("> initializing torch distributed ...", flush=True) |
| |
| if device_count > 0: |
| device = args.rank % device_count |
| if args.local_rank is not None: |
| assert ( |
| args.local_rank == device |
| ), "expected local-rank to be the same as rank % device-count." |
| else: |
| args.local_rank = device |
| torch.cuda.set_device(device) |
| |
| torch.distributed.init_process_group( |
| backend=args.distributed_backend, |
| world_size=args.world_size, |
| rank=args.rank, |
| timeout=timedelta(minutes=args.distributed_timeout_minutes), |
| ) |
|
|
| |
| |
| if device_count > 0: |
| if mpu.model_parallel_is_initialized(): |
| print("model parallel is already initialized") |
| else: |
| mpu.initialize_model_parallel( |
| args.tensor_model_parallel_size, |
| args.pipeline_model_parallel_size, |
| args.virtual_pipeline_model_parallel_size, |
| args.pipeline_model_parallel_split_rank, |
| ) |
|
|
| if args.rank == 0: |
| print( |
| f"> initialized tensor model parallel with size " |
| f"{mpu.get_tensor_model_parallel_world_size()}" |
| ) |
| print( |
| f"> initialized pipeline model parallel with size " |
| f"{mpu.get_pipeline_model_parallel_world_size()}" |
| ) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|