分布式预训练:PyTorch 分布式训练和启动脚本torch.distributed.launch torchrun slurm
1、DataParallel
如果当前有4个GPU,batch_size=16,那么模型将被复制到每一个GPU上,在前向传播时,每一个gpu将分到4个batch,每个gpu独立计算依据分到的batch计算出结果的梯度,然后将梯度返回到第一个GPU上,第一个GPU再进行梯度融合、模型更新。在下一次前向传播的时候,将更新后的模型再复制给每一个GPU。
1、DP在每个训练批次(batch)中,因为模型的权重都是在 一个进程上先算出来 然后再把他们分发到每个GPU上,所以网络通信就成为了一个瓶颈,而GPU使用率也通常很低。
2、因为它在每一次的前向传播的时候把模型也复制了(即每次更新都复制一遍模型),并且单进程多线程会造成GIL contention(全局解释器锁争用) 这里进程计算权重使通信成为瓶颈造成了大量的时间浪费,因此引入了DDP。
2、DistributedDataParallel
DDP采用多进程控制多GPU,共同训练模型,一份代码会被pytorch自动分配到n个进程并在n个GPU上运行。 DDP运用Ring-Reduce通信算法在每个GPU间对梯度进行通讯,交换彼此的梯度,从而获得所有GPU的梯度。对比DP,不需要在进行模型本体的通信,因此可以加速训练。
参考https://zhuanlan.zhihu.com/p/489011749
在所有节点上运行命令来初始化上面创建的 DDP 作业:
torchrun --nnodes=2 --nproc_per_node=8 --rdzv_id=100 --rdzv_backend=c10d --rdzv_endpoint=$MASTER_ADDR:29400 elastic_ddp.py
这里torchrun将启动8个进程并调用elastic_ddp.py 其启动的节点上的每个进程,但用户还需要应用slurm等集群管理工具才能在2个节点上实际运行此命令。
srun --nodes=2 ./torchrun_script.sh
启动脚本
无论 DDP 应用程序如何启动,每个进程都需要一种机制来了解其rank等,使用torch提供的分布式脚本可以通过环境变量将世界大小、全局等级、主地址和主端口以及本地等级作为命令行参数传递给每个实例,初始化的时候选择环境变量初始化就很方便 (就不应该使用启动子进程torch.multiprocessing.spawn 了)。
torch.distributed.launch
python -m torch.distributed.launch --nproc_per_node 8 test.py
————————————————
版权声明:本文为CSDN博主「www_z_dd」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/www_z_dd/article/details/132020726
参考:
PyTorch 分布式训练和启动脚本torch.distributed.launch torchrun slurm