[PP] Add pipeline parallelism (#5724)
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
"""Common utilities."""
|
||||
|
||||
import base64
|
||||
import builtins
|
||||
import ctypes
|
||||
@@ -414,16 +415,40 @@ class LayerFn(Protocol):
|
||||
def make_layers(
|
||||
num_hidden_layers: int,
|
||||
layer_fn: LayerFn,
|
||||
pp_rank: Optional[int] = None,
|
||||
pp_size: Optional[int] = None,
|
||||
prefix: str = "",
|
||||
return_tuple: bool = False,
|
||||
) -> Tuple[int, int, torch.nn.ModuleList]:
|
||||
"""Make a list of layers with the given layer function"""
|
||||
# circula imports
|
||||
from sglang.srt.distributed import get_pp_indices
|
||||
from sglang.srt.layers.utils import PPMissingLayer
|
||||
|
||||
assert not pp_size or num_hidden_layers >= pp_size
|
||||
start_layer, end_layer = (
|
||||
get_pp_indices(
|
||||
num_hidden_layers,
|
||||
pp_rank,
|
||||
pp_size,
|
||||
)
|
||||
if pp_rank is not None and pp_size is not None
|
||||
else (0, num_hidden_layers)
|
||||
)
|
||||
modules = torch.nn.ModuleList(
|
||||
[
|
||||
[PPMissingLayer(return_tuple=return_tuple) for _ in range(start_layer)]
|
||||
+ [
|
||||
maybe_offload_to_cpu(layer_fn(idx=idx, prefix=add_prefix(idx, prefix)))
|
||||
for idx in range(num_hidden_layers)
|
||||
for idx in range(start_layer, end_layer)
|
||||
]
|
||||
+ [
|
||||
PPMissingLayer(return_tuple=return_tuple)
|
||||
for _ in range(end_layer, num_hidden_layers)
|
||||
]
|
||||
)
|
||||
return modules
|
||||
if pp_rank is None or pp_size is None:
|
||||
return modules
|
||||
return modules, start_layer, end_layer
|
||||
|
||||
|
||||
def set_random_seed(seed: int) -> None:
|
||||
@@ -877,7 +902,7 @@ def broadcast_pyobj(
|
||||
"cuda" if torch.cuda.is_available() and not force_cpu_device else "cpu"
|
||||
)
|
||||
|
||||
if rank == 0:
|
||||
if rank == src:
|
||||
if len(data) == 0:
|
||||
tensor_size = torch.tensor([0], dtype=torch.long, device=device)
|
||||
dist.broadcast(tensor_size, src=src, group=dist_group)
|
||||
@@ -909,6 +934,50 @@ def broadcast_pyobj(
|
||||
return data
|
||||
|
||||
|
||||
def point_to_point_pyobj(
|
||||
data: List[Any],
|
||||
rank: int,
|
||||
group: Optional[torch.distributed.ProcessGroup] = None,
|
||||
src: int = 0,
|
||||
dst: int = 1,
|
||||
):
|
||||
"""Send data from src to dst in group."""
|
||||
|
||||
if rank == src:
|
||||
if len(data) == 0:
|
||||
tensor_size = torch.tensor([0], dtype=torch.long)
|
||||
dist.send(tensor_size, dst=dst, group=group)
|
||||
else:
|
||||
serialized_data = pickle.dumps(data)
|
||||
size = len(serialized_data)
|
||||
tensor_data = torch.ByteTensor(
|
||||
np.frombuffer(serialized_data, dtype=np.uint8)
|
||||
)
|
||||
tensor_size = torch.tensor([size], dtype=torch.long)
|
||||
|
||||
dist.send(tensor_size, dst=dst, group=group)
|
||||
dist.send(tensor_data, dst=dst, group=group)
|
||||
return data
|
||||
|
||||
elif rank == dst:
|
||||
tensor_size = torch.tensor([0], dtype=torch.long)
|
||||
dist.recv(tensor_size, src=src, group=group)
|
||||
size = tensor_size.item()
|
||||
|
||||
if size == 0:
|
||||
return []
|
||||
|
||||
tensor_data = torch.empty(size, dtype=torch.uint8)
|
||||
dist.recv(tensor_data, src=src, group=group)
|
||||
|
||||
serialized_data = bytes(tensor_data.cpu().numpy())
|
||||
data = pickle.loads(serialized_data)
|
||||
return data
|
||||
|
||||
# Other ranks in pp_group do nothing
|
||||
return []
|
||||
|
||||
|
||||
step_counter = 0
|
||||
|
||||
|
||||
@@ -1732,6 +1801,13 @@ def configure_ipv6(dist_init_addr):
|
||||
return port, host
|
||||
|
||||
|
||||
def rank0_log(msg: str):
|
||||
from sglang.srt.distributed import get_tensor_model_parallel_rank
|
||||
|
||||
if get_tensor_model_parallel_rank() == 0:
|
||||
logger.info(msg)
|
||||
|
||||
|
||||
def rank0_print(msg: str):
|
||||
from sglang.srt.distributed import get_tensor_model_parallel_rank
|
||||
|
||||
|
||||
Reference in New Issue
Block a user