main
py 166 lines 4.6 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 import dataclasses
4 import os
5 import traceback
6 from collections.abc import Callable
7 from typing import Any, Concatenate
8
9 import torch
10 from torch.multiprocessing import spawn # pyright: ignore[reportPrivateImportUsage]
11 from typing_extensions import ParamSpec
12
13 import vllm.envs as envs
14 from vllm.config import VllmConfig, set_current_vllm_config
15 from vllm.distributed import (
16 cleanup_dist_env_and_memory,
17 init_distributed_environment,
18 initialize_model_parallel,
19 )
20 from vllm.utils.network_utils import get_open_port
21
22 ## Parallel Processes Utils
23
24 P = ParamSpec("P")
25
26
27 @dataclasses.dataclass
28 class ProcessGroupInfo:
29 world_size: int
30 world_local_size: int
31 rank: int
32 node_rank: int
33 local_rank: int
34 device: torch.device
35
36
37 def _set_vllm_config(
38 vllm_config: VllmConfig, world_size: int, rank: int, local_rank: int
39 ):
40 import tempfile
41
42 temp_file = tempfile.mkstemp()[1]
43
44 # When DP is enabled, processes are organized as:
45 # rank = dp_rank * tp_pp_world_size + tp_pp_rank
46 tp_pp_world_size = vllm_config.parallel_config.world_size
47 vllm_config.parallel_config.data_parallel_rank = rank // tp_pp_world_size
48 tp_pp_rank = rank % tp_pp_world_size
49 vllm_config.parallel_config.rank = tp_pp_rank
50
51 with set_current_vllm_config(vllm_config):
52 init_distributed_environment(
53 world_size=tp_pp_world_size,
54 rank=tp_pp_rank,
55 distributed_init_method=f"file://{temp_file}",
56 local_rank=local_rank,
57 backend="nccl",
58 )
59
60 initialize_model_parallel(
61 tensor_model_parallel_size=vllm_config.parallel_config.tensor_parallel_size,
62 pipeline_model_parallel_size=vllm_config.parallel_config.pipeline_parallel_size,
63 )
64 if envs.VLLM_DISTRIBUTED_USE_SPLIT_GROUP:
65 cpu_group = torch.distributed.split_group(
66 split_ranks=[list(range(world_size))],
67 group_desc="moe_test_cpu",
68 )
69 else:
70 cpu_group = torch.distributed.new_group(
71 list(range(world_size)), backend="gloo"
72 )
73 return cpu_group
74
75
76 def _worker_parallel_launch(
77 local_rank: int,
78 world_size: int,
79 world_local_size: int,
80 node_rank: int,
81 init_method: str,
82 worker: Callable[..., None],
83 vllm_config: VllmConfig | None,
84 env_dict: dict | None,
85 worker_kwargs: dict[str, Any],
86 *args: Any,
87 ) -> None:
88 rank = node_rank * world_local_size + local_rank
89 device = torch.device("cuda", local_rank)
90 torch.accelerator.set_device_index(device)
91 torch.set_default_device(device)
92 torch.distributed.init_process_group(
93 backend="cpu:gloo,cuda:nccl",
94 init_method=init_method,
95 rank=rank,
96 world_size=world_size,
97 device_id=device,
98 )
99 barrier = torch.tensor([rank], device=device)
100 torch.distributed.all_reduce(barrier)
101
102 if env_dict is not None:
103 os.environ.update(env_dict)
104
105 cpu_group = None
106 if vllm_config is not None:
107 cpu_group = _set_vllm_config(vllm_config, world_size, rank, local_rank)
108
109 def _run_worker():
110 worker(
111 ProcessGroupInfo(
112 world_size=world_size,
113 world_local_size=world_local_size,
114 rank=rank,
115 node_rank=node_rank,
116 local_rank=local_rank,
117 device=device,
118 ),
119 vllm_config,
120 cpu_group,
121 *args,
122 **worker_kwargs,
123 )
124
125 try:
126 if vllm_config is not None:
127 with set_current_vllm_config(vllm_config):
128 _run_worker()
129 else:
130 _run_worker()
131 except Exception as ex:
132 print(ex)
133 traceback.print_exc()
134 raise
135 finally:
136 torch.accelerator.synchronize()
137 if vllm_config is not None:
138 cleanup_dist_env_and_memory()
139 else:
140 torch.distributed.destroy_process_group()
141
142
143 def parallel_launch_with_config(
144 world_size: int,
145 worker: Callable[Concatenate[ProcessGroupInfo, VllmConfig, Any, P], None],
146 vllm_config: VllmConfig,
147 env_dict: dict[Any, Any] | None,
148 *args: P.args,
149 **kwargs: P.kwargs,
150 ) -> None:
151 spawn(
152 _worker_parallel_launch,
153 args=(
154 world_size,
155 world_size,
156 0,
157 f"tcp://{os.getenv('LOCALHOST', 'localhost')}:{get_open_port()}",
158 worker,
159 vllm_config,
160 env_dict,
161 kwargs,
162 )
163 + args,
164 nprocs=world_size,
165 join=True,
166 )