PyTorch分布式与多进程异常求助:进程执行全脚本且程序冻结
问题1:为何spawn创建的进程会执行output_0部分?
你犯了一个核心错误:同时混用了torchrun和torch.multiprocessing.spawn。
torchrun本身就是PyTorch官方用来启动分布式多进程的工具,它会根据--nproc_per_node参数自动创建对应数量的进程,每个进程都会完整执行你的脚本代码。而你在if __name__ == '__main__':块里又调用了mp.spawn,相当于每个torchrun启动的进程都会再创建world_size个子进程,形成了进程嵌套。
那些重复的ngpus = 4 world_size = 4输出,本质是每个torchrun启动的进程都进入了__main__代码块执行了print语句,并非spawn创建的子进程导致的。
问题2:为何程序输出部分内容后冻结?
主要有两个原因:
- 进程嵌套引发的资源冲突与死锁:
torchrun创建的4个进程各自通过mp.spawn再生成4个子进程,总计16个子进程加4个父进程,大量进程同时初始化NCCL进程组,极易引发资源竞争和死锁。 - 未正确清理分布式进程组:你的
print_tensors函数仅初始化了dist.init_process_group,但函数结束时没有调用dist.destroy_process_group()释放资源。分布式进程在未正确销毁进程组的情况下,会一直等待同步信号,导致程序挂起。
修复方案
你需要二选一使用启动方式,不能混用。推荐采用torchrun的标准写法:
修改后的脚本:
import os import torch import torch.cuda as cuda import torch.distributed as dist def main(): rank = int(os.environ['RANK']) world_size = int(os.environ['WORLD_SIZE']) cuda.set_device(rank) dist.init_process_group(backend='nccl', init_method='env://', world_size=world_size) print(f'{rank} -> {torch.randn(2)}') # 必须销毁进程组,保证进程正常退出 dist.destroy_process_group() if __name__ == '__main__': main()
启动命令保持不变:
torchrun \ --nnodes=1 \ --nproc_per_node=4 \ test.py \
修改后,torchrun会为每个GPU创建一个独立进程,每个进程执行main函数,完成初始化、打印、资源清理的完整流程,不会再出现重复输出和冻结问题。
单GPU运行时正常只是巧合——此时torchrun仅创建1个进程,没有嵌套,且单进程下分布式进程组的初始化/销毁不会触发死锁,但这并非正确的分布式写法。
内容的提问来源于stack exchange,提问作者Mecreative
相关产品推荐
相关产品推荐

