Repository navigation
feat(tp): run one tensor-parallel group across nodes #2647
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
ce21227
c59ffd5
c3cc236
24049fe
7742448
2b10dd6
3095411
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1069,6 +1069,14 @@ class ParallelConfig: | |
|
|
||
| data_parallel_master_ip: str = "127.0.0.1" | ||
|
|
||
| tensor_parallel_size_local: int | None = None | ||
| """TP ranks (model-runner workers) this node runs. None means all of them, | ||
| the single-node case. Set it below tensor_parallel_size to spread one TP | ||
| group over several nodes; see atom/model_engine/tp_multinode.py.""" | ||
| tensor_parallel_rank: int = 0 | ||
| """First TP rank this node runs. The node that runs rank 0 also runs the | ||
| engine and the API server; the others run only their workers.""" | ||
|
|
||
| @property | ||
| def is_multinode_dp(self) -> bool: | ||
| """Whether this node owns only part of the global DP group. | ||
|
|
@@ -2207,6 +2215,61 @@ def tp_world_size(self) -> int: | |
| visible = torch.cuda.device_count() | ||
| return visible if 0 < visible < tp else tp | ||
|
|
||
| @property | ||
| def tp_size_local(self) -> int: | ||
| """TP worker processes on this node: fewer than `tp_world_size` when | ||
| one TP group spans several nodes.""" | ||
| local = self.parallel_config.tensor_parallel_size_local | ||
| return self.tp_world_size if local is None else local | ||
|
|
||
| @property | ||
| def tp_rank_start(self) -> int: | ||
| """First TP rank on this node; it runs `tp_size_local` ranks from here.""" | ||
| return self.parallel_config.tensor_parallel_rank | ||
|
|
||
| @property | ||
| def is_multinode_tp(self) -> bool: | ||
| return self.tp_size_local < self.tp_world_size or self.tp_rank_start > 0 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. local > tp is accepted and silently ignored here? validate whenever either flag was set |
||
|
|
||
| def _check_multinode_tp(self) -> None: | ||
| pc = self.parallel_config | ||
| if pc.tensor_parallel_size_local is None and pc.tensor_parallel_rank == 0: | ||
| return | ||
| local, start, tp = self.tp_size_local, self.tp_rank_start, self.tp_world_size | ||
| if local < 1 or tp % local or start % local or not 0 <= start < tp: | ||
| raise ValueError( | ||
| f"--tensor-parallel-size-local {local} and --tensor-parallel-rank " | ||
| f"{start} must cut -tp {tp} into whole, equal per-node slices" | ||
| ) | ||
| if not self.is_multinode_tp: | ||
| return | ||
| unsupported = [ | ||
| name | ||
| for name, used in ( | ||
| ("data parallelism", pc.data_parallel_size > 1), | ||
| ("--enable-dp-attention", self.enable_dp_attention), | ||
| ("pipeline parallelism", self.pipeline_parallel_size > 1), | ||
| ("prefill context parallelism", self.prefill_context_parallel_size > 1), | ||
| ("--fake-eplb", self.fake_eplb), | ||
| ("RapidServe", self.enable_rapidserve), | ||
| ) | ||
| if used | ||
| ] | ||
| if unsupported: | ||
| raise ValueError( | ||
| "tensor parallelism across nodes does not support " | ||
| + ", ".join(unsupported) | ||
| ) | ||
| if pc.data_parallel_base_port == 0 or pc.data_parallel_master_ip in ( | ||
| "127.0.0.1", | ||
| "localhost", | ||
| ): | ||
| raise ValueError( | ||
| "tensor parallelism across nodes needs --data-parallel-master-ip " | ||
| "set to the address of the node that runs TP rank 0, and the " | ||
| "same nonzero --data-parallel-base-port on every node" | ||
| ) | ||
|
|
||
| @property | ||
| def capture_sizes(self) -> list[int]: | ||
| """The declared CUDAGraph capture ladder, in batch sizes. | ||
|
|
@@ -2380,6 +2443,7 @@ def __post_init__(self): | |
| ) | ||
|
|
||
| assert 1 <= self.tensor_parallel_size <= 8 | ||
| self._check_multinode_tp() | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. test bypasses post_init, so reverting this line still passes. pin the call site? |
||
| if self.decode_context_parallel_size > 1: | ||
| assert self.tensor_parallel_size % self.decode_context_parallel_size == 0, ( | ||
| f"tp_size ({self.tensor_parallel_size}) must be divisible by " | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
local 16 with tp 8 is silently ignored here, gate on flags set and reject local > tp?