[PP] Add pipeline parallelism (#5724)

This commit is contained in:
Ying Sheng
2025-04-30 18:18:07 -07:00
committed by GitHub
parent e97e57e699
commit 11383cec3c
25 changed files with 1150 additions and 308 deletions

View File

@@ -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