utils.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. # Copyright 2023 The PygmalionAI team.
  2. # Copyright 2023 The vLLM team.
  3. # Adapted from
  4. # https://github.com/NVIDIA/Megatron-LM/blob/main/megatron/core/tensor_parallel/utils.py
  5. # Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
  6. from typing import Sequence, Tuple
  7. import torch
  8. import aphrodite.common.envs as envs
  9. APHRODITE_PP_LAYER_PARTITION = envs.APHRODITE_PP_LAYER_PARTITION
  10. def ensure_divisibility(numerator, denominator):
  11. """Ensure that numerator is divisible by the denominator."""
  12. assert numerator % denominator == 0, "{} is not divisible by {}".format(
  13. numerator, denominator)
  14. def divide(numerator, denominator):
  15. """Ensure that numerator is divisible by the denominator and return
  16. the division value."""
  17. ensure_divisibility(numerator, denominator)
  18. return numerator // denominator
  19. def split_tensor_along_last_dim(
  20. tensor: torch.Tensor,
  21. num_partitions: int,
  22. contiguous_split_chunks: bool = False,
  23. ) -> Sequence[torch.Tensor]:
  24. """ Split a tensor along its last dimension.
  25. Arguments:
  26. tensor: input tensor.
  27. num_partitions: number of partitions to split the tensor
  28. contiguous_split_chunks: If True, make each chunk contiguous
  29. in memory.
  30. Returns:
  31. A list of Tensors
  32. """
  33. # Get the size and dimension.
  34. last_dim = tensor.dim() - 1
  35. last_dim_size = divide(tensor.size()[last_dim], num_partitions)
  36. # Split.
  37. tensor_list = torch.split(tensor, last_dim_size, dim=last_dim)
  38. # NOTE: torch.split does not create contiguous tensors by default.
  39. if contiguous_split_chunks:
  40. return tuple(chunk.contiguous() for chunk in tensor_list)
  41. return tensor_list
  42. def get_pp_indices(num_hidden_layers: int, pp_rank: int,
  43. pp_size: int) -> Tuple[int, int]:
  44. """Try to evenly distribute layers across partitions.
  45. If the number of layers is not divisible by the number of partitions,
  46. the last partition will have the remaining layers.
  47. """
  48. partition_list_str = APHRODITE_PP_LAYER_PARTITION
  49. if partition_list_str is not None:
  50. try:
  51. partitions = [
  52. int(layer) for layer in partition_list_str.split(",")
  53. ]
  54. except ValueError as err:
  55. raise ValueError("Invalid partition string: {}".format(
  56. partition_list_str)) from err
  57. if len(partitions) != pp_size:
  58. raise ValueError(f"{len(partitions)=} does not match {pp_size=}.")
  59. if sum(partitions) != num_hidden_layers:
  60. raise ValueError(
  61. f"{sum(partitions)=} does not match {num_hidden_layers=}.")
  62. start_layer = sum(partitions[:pp_rank])
  63. end_layer = start_layer + partitions[pp_rank]
  64. else:
  65. layers_per_partition = num_hidden_layers // pp_size
  66. start_layer = pp_rank * layers_per_partition
  67. end_layer = start_layer + layers_per_partition
  68. if pp_rank == pp_size - 1:
  69. end_layer = num_hidden_layers
  70. return (start_layer, end_layer)