Instructions to use KexuanShi/Megatron-LM with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- NeMo
How to use KexuanShi/Megatron-LM with NeMo:
# tag did not correspond to a valid NeMo domain.
- Notebooks
- Google Colab
- Kaggle
| # Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. | |
| from typing import List, Sequence | |
| import torch | |
| from megatron.core.utils import ( | |
| divide, | |
| get_tensor_model_parallel_group_if_none, | |
| is_torch_min_version, | |
| ) | |
| try: | |
| if is_torch_min_version("1.13.0"): | |
| dist_all_gather_func = torch.distributed.all_gather_into_tensor | |
| else: | |
| dist_all_gather_func = torch.distributed._all_gather_base | |
| except Exception: | |
| dist_all_gather_func = torch.distributed._all_gather_base | |
| def split_tensor_along_last_dim( | |
| tensor: torch.Tensor, num_partitions: int, contiguous_split_chunks: bool = False | |
| ) -> List[torch.Tensor]: | |
| """Split a tensor along its last dimension. | |
| Args: | |
| tensor: input tensor. | |
| num_partitions: number of partitions to split the tensor | |
| contiguous_split_chunks: If True, make each chunk contiguous | |
| in memory. | |
| Returns: | |
| A list of Tensors | |
| """ | |
| # Get the size and dimension. | |
| last_dim = tensor.dim() - 1 | |
| last_dim_size = divide(tensor.size()[last_dim], num_partitions) | |
| # Split. | |
| tensor_list = torch.split(tensor, last_dim_size, dim=last_dim) | |
| # Note: torch.split does not create contiguous tensors by default. | |
| if contiguous_split_chunks: | |
| return tuple(chunk.contiguous() for chunk in tensor_list) | |
| return tensor_list | |
| def split_tensor_into_1d_equal_chunks(tensor, new_buffer=False, tp_group=None): | |
| """Break a tensor into equal 1D chunks across tensor parallel ranks. | |
| Returns a Tensor or View with this rank's portion of the data. | |
| Args: | |
| tensor: The tensor to split | |
| Keyword Args: | |
| new_buffer (bool): If True, returns a new Tensor. | |
| If False, returns a view into the existing Tensor. | |
| Default is False | |
| """ | |
| tp_group = get_tensor_model_parallel_group_if_none(tp_group) | |
| partition_size = torch.numel(tensor) // tp_group.size() | |
| start_index = partition_size * tp_group.rank() | |
| end_index = start_index + partition_size | |
| if new_buffer: | |
| data = torch.empty( | |
| partition_size, | |
| dtype=tensor.dtype, | |
| device=torch.cuda.current_device(), | |
| requires_grad=False, | |
| ) | |
| data.copy_(tensor.view(-1)[start_index:end_index]) | |
| else: | |
| data = tensor.view(-1)[start_index:end_index] | |
| return data | |
| def gather_split_1d_tensor(tensor, tp_group=None): | |
| """Opposite of split_tensor_into_1d_equal_chunks. Gather values from tensor | |
| model parallel ranks. | |
| Returns a new Tensor with the gathered data. | |
| Args: | |
| tensor: A Tensor or view of this rank's portion of the data. | |
| """ | |
| tp_group = get_tensor_model_parallel_group_if_none(tp_group) | |
| numel_gathered = torch.numel(tensor) * tp_group.size() | |
| gathered = torch.empty( | |
| numel_gathered, dtype=tensor.dtype, device=torch.cuda.current_device(), requires_grad=False | |
| ) | |
| dist_all_gather_func(gathered, tensor, group=tp_group) | |
| return gathered | |
| class VocabUtility: | |
| """Split the vocabulary into `world_size` chunks and return the first | |
| and last index of the vocabulary belonging to the `rank` | |
| partition: Note that indices in [fist, last) | |
| """ | |
| def vocab_range_from_per_partition_vocab_size( | |
| per_partition_vocab_size: int, rank, world_size: int | |
| ) -> Sequence[int]: | |
| """Vocab range from per partition vocab size.""" | |
| index_f = rank * per_partition_vocab_size | |
| index_l = index_f + per_partition_vocab_size | |
| return index_f, index_l | |
| def vocab_range_from_global_vocab_size( | |
| global_vocab_size: int, rank: int, world_size: int | |
| ) -> Sequence[int]: | |
| """Vocab range from global vocab size.""" | |
| per_partition_vocab_size = divide(global_vocab_size, world_size) | |
| return VocabUtility.vocab_range_from_per_partition_vocab_size( | |
| per_partition_vocab_size, rank, world_size | |
| ) | |