acoustic-van-30942
06/27/2023, 6:49 PMClusterEnvironment for multi-node multi-GPU training? I'm stuck on deriving the LOCAL_RANK , which isn't provided as an environment variable using @pytorch_parallel.
Thanks in advance!acoustic-van-30942
06/27/2023, 9:26 PMclass MetaflowEnvironment(ClusterEnvironment):
"""
Quick Dirty MF environment in PTL for Single GPU Multi-node training.
"""
@property
def creates_processes_externally(self) -> bool:
return True
@property
def main_address(self) -> str:
return current.parallel.main_ip
@property
def main_port(self) -> int:
return 9001 # Fix me
@staticmethod
def detect() -> bool:
return True
def world_size(self) -> int:
return int(current.parallel.num_nodes) * int(N_GPU)
def set_world_size(self, size: int) -> None:
logging.debug("MetaflowEnvironment.set_world_size was called, but setting world size is not allowed. Ignored.")
def global_rank(self) -> int:
return int(current.parallel.node_index)
def set_global_rank(self, rank: int) -> None:
logging.debug("MetaflowEnvironment.set_global_rank was called, but setting global rank is not allowed. Ignored.")
def local_rank(self) -> int:
return os.environ.get("LOCAL_RANK", 0)
def node_rank(self) -> int:
return self.global_rank()
Getting the following - it times out after 30 mins
INFO:torch.distributed.distributed_c10d:Waiting in store based barrier to initialize process group for rank: 2, key: store_based_barrier_key:1 (world_size=16, worker_count=3, timeout=0:30:00)curved-island-17262
06/28/2023, 3:51 AMTORCH_DISTRIBUTED_DEBUG=DETAIL & TORCH_SHOW_CPP_STACKTRACES=1 to get more logs?acoustic-van-30942
06/28/2023, 8:01 AMcurved-island-17262
06/28/2023, 8:07 AMancient-application-36103
06/28/2023, 5:01 PMNODE_RANK which is set by metaflow?ancient-application-36103
06/28/2023, 5:02 PMacoustic-van-30942
06/28/2023, 5:05 PMFSDP and Deepspeed strategies within PTL mess up the environment variables and thus require a custom PTL ClusterEnvironment . That set-up I'm a little unsure about w/ regards to multi-node multi-GPU training. @hallowed-glass-14538 was able to figure out the right ClusterEnvironment for multi-node single GPU, but we will need to do multi-node multi-gpu in the near future for training LLMs.hallowed-glass-14538
06/28/2023, 5:13 PMacoustic-van-30942
06/28/2023, 5:14 PMhallowed-glass-14538
06/28/2023, 5:22 PMimport os
from lightning.pytorch.plugins.environments import ClusterEnvironment
from metaflow import current
class MetaflowEnvironment(ClusterEnvironment):
"""
Quick Dirty MF environment in PTL for Single GPU Multi-node training.
"""
@property
def creates_processes_externally(self) -> bool:
return True
@property
def main_address(self) -> str:
return current.parallel.main_ip
@property
def main_port(self) -> int:
return 9001 # Fix me
@staticmethod
def detect() -> bool:
return True
def world_size(self) -> int:
return int(current.parallel.num_nodes) * int(N_GPU)
def set_world_size(self, size: int) -> None:
logging.debug("MetaflowEnvironment.set_world_size was called, but setting world size is not allowed. Ignored.")
def global_rank(self) -> int:
return int(current.parallel.node_index) * int(N_GPU) + int(os.environ.get("LOCAL_RANK", 0))
def set_global_rank(self, rank: int) -> None:
logging.debug("MetaflowEnvironment.set_global_rank was called, but setting global rank is not allowed. Ignored.")
def local_rank(self) -> int:
return os.environ.get("LOCAL_RANK", 0)
def node_rank(self) -> int:
return int(current.parallel.node_index)
I forgot where LOCAL_RANK was set in the code. do you know?hallowed-glass-14538
06/28/2023, 5:23 PMglobal_rank is computedacoustic-van-30942
06/28/2023, 5:24 PMhallowed-glass-14538
06/28/2023, 5:33 PMhallowed-glass-14538
06/28/2023, 5:34 PMacoustic-van-30942
06/28/2023, 5:34 PMhallowed-glass-14538
06/28/2023, 5:47 PMacoustic-van-30942
06/28/2023, 5:48 PMhallowed-glass-14538
06/28/2023, 5:52 PMnum_nodes = current.parallel.num_nodes. You can even just use the @parallel decorator since @pytorch_parallel maybe setting worldsize which might be incorrect.
@pytorch_parallel is only syntactic sugar over @parallel; All the environment information is anyways being set in the ClusterEnvironmentacoustic-van-30942
06/28/2023, 5:53 PMacoustic-van-30942
06/28/2023, 6:31 PMRuntimeError: Timed out initializing process group in store based barrier on rank: 4, for key: store_based_barrier_key:1 (world_size=16, worker_count=4, timeout=0:30:00)acoustic-van-30942
06/28/2023, 6:46 PMhallowed-glass-14538
06/28/2023, 6:48 PMacoustic-van-30942
06/28/2023, 6:49 PMhallowed-glass-14538
06/30/2023, 2:19 AMhallowed-glass-14538
06/30/2023, 2:21 AMacoustic-van-30942
06/30/2023, 3:11 AMddp repo so it's not so confusing.
But essentially, we are testing the following strategies w/ Metaflow: ddp, fsp, deepspeed with PTLacoustic-van-30942
06/30/2023, 3:58 AMhallowed-glass-14538
06/30/2023, 11:40 PMtorchrun ; I think this can unblock you. We can find better ways of handling this once we can get something working.
This is so that PTL can launch additional subprocesses from the same script.
Let me know if this helpsacoustic-van-30942
06/30/2023, 11:44 PMsubprocess and run the training as a script.
Do you know why we were able to get multi-node single GPU working w/ DDP/FSDP without the need for subprocess ?hallowed-glass-14538
06/30/2023, 11:56 PMacoustic-van-30942
06/30/2023, 11:57 PMhallowed-glass-14538
07/01/2023, 12:00 AMacoustic-van-30942
07/01/2023, 12:02 AMargparsehallowed-glass-14538
07/01/2023, 12:17 AMacoustic-van-30942
07/01/2023, 12:17 AM1.7.7acoustic-van-30942
07/05/2023, 1:09 AM0it [23:00, ?it/s]
2023-07-05 01:08:17 INFO [torch.distributed.distributed_c10d] Waiting in store based barrier to initialize process group for rank: 8, key: store_based_barrier_key:1 (world_size=16, worker_count=3, timeout=0:30:00)acoustic-van-30942
07/05/2023, 1:16 AMhallowed-glass-14538
07/05/2023, 1:39 AMacoustic-van-30942
07/05/2023, 2:07 AMacoustic-van-30942
07/05/2023, 3:45 AMg5.12xlarge instances (ea. has 4 GPUs). Is WORLD_SIZE 4 or 4*4 = 16?hallowed-glass-14538
07/05/2023, 6:36 PMhallowed-glass-14538
07/05/2023, 6:44 PMTORCH_DISTRIBUTED_DEBUG=INFO as environment variable and then send the logs ?acoustic-van-30942
07/05/2023, 6:46 PMTORCH_DISTRIBUTED_DEBUG=INFO as an environment variable now and send logs shortly.acoustic-van-30942
07/05/2023, 7:08 PMTORCH_DISTRIBUTED_DEBUG set.
It just says:
INFO [torch.distributed.distributed_c10d] Waiting in store based barrier to initialize process group for rank: 8, key: store_based_barrier_key:1 (world_size=16, worker_count=3, timeout=0:30:00)hallowed-glass-14538
07/05/2023, 7:09 PMacoustic-van-30942
07/05/2023, 7:10 PMhallowed-glass-14538
07/05/2023, 7:11 PMacoustic-van-30942
07/05/2023, 7:12 PMhallowed-glass-14538
07/05/2023, 7:12 PMacoustic-van-30942
07/05/2023, 7:13 PMhallowed-glass-14538
07/05/2023, 7:20 PM8 ?acoustic-van-30942
07/05/2023, 7:21 PMacoustic-van-30942
07/05/2023, 7:22 PMhallowed-glass-14538
07/05/2023, 7:23 PMhallowed-glass-14538
07/05/2023, 7:23 PMhallowed-glass-14538
07/05/2023, 7:48 PMcreates_processes_externally in MetaflowEnvionment ; Can you change to that returning Falsehallowed-glass-14538
07/05/2023, 7:49 PMacoustic-van-30942
07/05/2023, 7:50 PMacoustic-van-30942
07/05/2023, 8:05 PMacoustic-van-30942
07/05/2023, 8:09 PMlocal_rank to int . I think that's the issue.hallowed-glass-14538
07/05/2023, 8:41 PMacoustic-van-30942
07/05/2023, 8:41 PMacoustic-van-30942
07/05/2023, 10:32 PMRuntimeError: Lightning attempted to launch new distributed processes with `local_rank > 0`. This should not happen. Possible reasons: 1) LOCAL_RANK environment variable was incorrectly modified by the user, 2) `ClusterEnvironment.creates_processes_externally` incorrectly implemented.hallowed-glass-14538
07/05/2023, 10:35 PMacoustic-van-30942
07/05/2023, 10:36 PMhallowed-glass-14538
07/05/2023, 10:40 PMhallowed-glass-14538
07/05/2023, 10:40 PMacoustic-van-30942
07/05/2023, 10:41 PMhallowed-glass-14538
07/05/2023, 11:20 PMfrom metaflow import current
subprocess.run(
[
"torchrun",
f"--nproc_per_node={str(self.n_gpu)}",
f"--nnodes={str(self.num_nodes)}",
f"--rdzv-id={current.run_id}",
"--rdzv-backend=c10d",
f"--rdzv-endpoint={current.parallel.main_ip}:29400",
"ddp_trainer.py",
"--output-dir", self.output_dir,
"--source-max-token-length", self.source_max_token_length,
"--target-max-token-length", self.target_max_token_length,
"--batch-size", self.batch_size,
"--max-epochs", self.max_epochs,
"--learning-rate", self.learning_rate,
"--weight-decay", self.weight_decay,
"--adam-epsilon", self.adam_epsilon,
"--warmup-steps", self.warmup_steps,
"--gradient-accumulation-steps", self.gradient_accumulation_steps,
"--n-gpu", self.n_gpu,
"--num-nodes=%d" % self.num_nodes,
"--early-stopping-patience-epochs", self.early_stopping_patience_epochs,
"--precision", self.precision,
"--logger", self.logger,
"--dataloader-num-workers", self.dataloader_num_workers,
"--opt-level", self.opt_level,
"--max-grad-norm", self.max_grad_norm,
"--seed", self.seed,
]
+ (["--early-stop-callback"] if self.early_stop_callback else [])
+ (["--save-only-last-epoch"] if self.save_only_last_epoch else [])
+ (["--fp-16"] if self.fp_16 else [])
+ (["--use-gpu"] if self.use_gpu else []),
check=True,
)acoustic-van-30942
07/05/2023, 11:22 PMacoustic-van-30942
07/05/2023, 11:36 PMtorchrun: error: unrecognized arguments: --rdzv-id=286 --rdzv-backend=c10d --rdzv-endpoint=10.14.51.223:29400hallowed-glass-14538
07/05/2023, 11:43 PMfrom metaflow import current
subprocess.run(
[
"torchrun",
f"--nproc_per_node={str(self.n_gpu)}",
f"--nnodes={str(self.num_nodes)}",
f"--rdzv_id=metaflow_{current.run_id}",
"--rdzv_backend=c10d",
f"--rdzv_endpoint={current.parallel.main_ip}:29400",
"ddp_trainer.py",
"--output-dir", self.output_dir,
"--source-max-token-length", self.source_max_token_length,
"--target-max-token-length", self.target_max_token_length,
"--batch-size", self.batch_size,
"--max-epochs", self.max_epochs,
"--learning-rate", self.learning_rate,
"--weight-decay", self.weight_decay,
"--adam-epsilon", self.adam_epsilon,
"--warmup-steps", self.warmup_steps,
"--gradient-accumulation-steps", self.gradient_accumulation_steps,
"--n-gpu", self.n_gpu,
"--num-nodes=%d" % self.num_nodes,
"--early-stopping-patience-epochs", self.early_stopping_patience_epochs,
"--precision", self.precision,
"--logger", self.logger,
"--dataloader-num-workers", self.dataloader_num_workers,
"--opt-level", self.opt_level,
"--max-grad-norm", self.max_grad_norm,
"--seed", self.seed,
]
+ (["--early-stop-callback"] if self.early_stop_callback else [])
+ (["--save-only-last-epoch"] if self.save_only_last_epoch else [])
+ (["--fp-16"] if self.fp_16 else [])
+ (["--use-gpu"] if self.use_gpu else []),
check=True,
)hallowed-glass-14538
07/05/2023, 11:54 PMacoustic-van-30942
07/05/2023, 11:54 PMhallowed-glass-14538
07/06/2023, 12:01 AMacoustic-van-30942
07/06/2023, 12:01 AMacoustic-van-30942
07/06/2023, 12:02 AMcreates_processes_externally back to Truehallowed-glass-14538
07/06/2023, 12:06 AMnproc-per-node ; But apparently it isn't.hallowed-glass-14538
07/06/2023, 12:07 AMacoustic-van-30942
07/06/2023, 12:12 AMhallowed-glass-14538
07/06/2023, 12:15 AM'--nproc_per_node=-1' in the calledProcessErrorhallowed-glass-14538
07/06/2023, 12:15 AMn_gpu parameter is being set to -1hallowed-glass-14538
07/06/2023, 12:15 AMacoustic-van-30942
07/06/2023, 12:17 AMacoustic-van-30942
07/06/2023, 12:30 AMacoustic-van-30942
07/06/2023, 12:30 AMacoustic-van-30942
07/06/2023, 12:32 AMacoustic-van-30942
07/06/2023, 3:18 AM"NCCL_SHM_DISABLE": "1" . Not sure what the ramifications are, but hopefully should be ok.
Thanks so much for your help on this! REALLY appreciate it.
Next, I will want to test FSDP + Deepspeed on PTL.acoustic-van-30942
07/06/2023, 11:27 PMsubprocess and then torchrun. I just fear our users will immediately compare this to Ray where the setup is a bit easier and abstracts a lot of the complicated stuff away: https://devblog.pytorchlightning.ai/introducing-ray-lightning-multi-node-pytorch-lightning-training-made-easy-30ed075209f0ancient-application-36103
07/07/2023, 1:25 AMacoustic-van-30942
07/07/2023, 6:24 PM@parallel decorator. It's using 4 g5.12xlarge instances. Thanks so much for your help
I added a reproducible example here if it helps anyone else: https://github.com/rileyhun/llm_finetuning_metaflow/tree/main/pytorch-deepspeed
@crooked-jordan-29960 By sheer coincidence, I also was able to get the progress bar to show up as well. I'm not really sure how or why though...All I did was print the loss (see here) and it allowed me to see the progress. If I remove the print statements though, the progress bar is suppressed. Any insight on this?hallowed-glass-14538
07/07/2023, 7:22 PMParameters would only be things like num_gpus, loggers , seed, use_gpu , `dataloader_num_workers`etc. The config_file can be on additional parameter that holds everything needed by PTL.
iii. You can reduce the deps you install like click ;
iv. The internal teams can follow the pattern of using LightningCLI to create Models but the "training pipeline" is semi-general purpose to plug-in different models which expose a lightning CLI.
v. Potentially this can be a way of abstracting out torchrun from users since users develop isolated modules that expose CLIs and config files; While the training pipeline takes care of passing things into the training code and running it at scale. (this will surely have it's own gotchas as I have not yet played much with PTL's cli)
2. When it comes abstracting out torchrun, one way to do this is to have a ray like approach of creating a strategy but one thing I am still not clear about is how we will launch sub-processes since torch distributed expects us to call the same script multiple times with different env variables. If the training loop is in the "main-process" (ie. the process launched by metaflow on remote) then we in a bind (of sorts) since Metaflow's cli won't play nice with calling itself.
3. The key distinction between ray and MF here is that:
a. ray will run inside PTL's context meaning ray will launch jobs from within PTL's codebase; The compute is configured once outside PTL's context but the compute is accessed within PTL's context.
b. MF is currently running outside PTL's codebase and also launches jobs outside PTL's codebase. MF will also dynamically configure/launch compute (batch-array specs based on resources in decorator);
There is much we can explore here. Can we have a call sometime next week to discuss all the hurdles you faced while getting this running? This will help us understand better the abstractions we should provide to build this.acoustic-van-30942
07/07/2023, 7:31 PMhallowed-glass-14538
07/07/2023, 7:44 PMacoustic-van-30942
07/07/2023, 7:55 PMmicroscopic-painting-61536
03/28/2024, 5:56 PMancient-application-36103
03/28/2024, 5:58 PM