当我在ddp模式(2个GPU)下启动我的主要脚本时,Pytorch Lightning会复制在主要脚本中执行的所有内容,例如打印或其他逻辑。我需要一些扩展训练逻辑,我希望自己处理。例如,在Trainer.fit()
之后执行某些操作(仅一次!)。但是由于主要脚本的复制,这并不按照我想象的方式工作。我也尝试将其包装在if __name__ == "__main__"
中,但它并没有改变行为。如何解决这个问题?或者说,如何在不复制主要脚本的情况下使用一些关于我的Trainer对象的逻辑?
当我在ddp模式(2个GPU)下启动我的主要脚本时,Pytorch Lightning会复制在主要脚本中执行的所有内容,例如打印或其他逻辑。我需要一些扩展训练逻辑,我希望自己处理。例如,在Trainer.fit()
之后执行某些操作(仅一次!)。但是由于主要脚本的复制,这并不按照我想象的方式工作。我也尝试将其包装在if __name__ == "__main__"
中,但它并没有改变行为。如何解决这个问题?或者说,如何在不复制主要脚本的情况下使用一些关于我的Trainer对象的逻辑?
我在 GitHub 仓库上询问了这个问题:https://github.com/PyTorchLightning/pytorch-lightning/issues/8563
有不同的加速器可用于训练,而 DDP(DistributedDataParallel)每个 GPU 运行一次脚本,但 ddp_spawn 和 dp 不会。
然而,某些插件(如 DeepSpeedPlugin)是基于 DDP 构建的,因此更改加速器并不会阻止主要脚本多次运行。
您可以在Trainer.fit
之后添加以下代码来停止重复的子进程:
import sys
if model.global_rank != 0:
sys.exit(0)
其中 model
继承自 LightningModule
,后者具有一个属性 global_rank
,指定了机器的排名。我们可以大致理解为 gpu id 或进程 id。这段代码之后的所有内容只会在主进程中执行,即 global_rank
= 0 的进程。
更多信息,请参考文档 https://pytorch-lightning.readthedocs.io/en/latest/common/lightning_module.html#global_rank
import os
if __name__ == "__main__":
if 'LOCAL_RANK' not in os.environ.keys() and 'NODE_RANK' not in os.environ.keys():
# code you only want to run once
使用全局变量:
if __name__ == "__main__":
is_primary = os.environ.get(IS_PTL_PRIMARY) is None
os.environ[IS_PTL_PRIMARY] = "yes"
## code to run on each GPU
if is_primary:
## code to run only once