赞
踩
flyfish
环境:
Python>=3.6.0
PyTorch>=1.7
YOLOv5:v5
通过设置CUDA_VISIBLE_DEVICES环境变量来限制PyTorch所能使用的GPU设备,GPU设备从0开始编号。
在命令行中设置
CUDA_VISIBLE_DEVICES='0,1,2,3,4,5,6,7'
在代码设置,该代码需要写在调用GPU资源之前
os.environ["CUDA_VISIBLE_DEVICES"] = '0,1,2,3,4,5,6,7'
分两种类型机器一个master,其他都是slave
python -m torch.distributed.launch --nproc_per_node G --nnodes N --node_rank 0 --master_addr "192.168.1.2" --master_port 1234 train.py --batch 64 --data coco.yaml --cfg yolov5s.yaml --weights ''
python -m torch.distributed.launch --nproc_per_node G --nnodes N --node_rank R --master_addr "192.168.1.2" --master_port 1234 train.py --batch 64 --data coco.yaml --cfg yolov5s.yaml --weights ''
假设有两台机器,每台机器都有两张卡
python -m torch.distributed.launch --nproc_per_node 2 --nnodes 2 --node_rank 0 --master_addr "192.168.1.2" --master_port 1234 train.py --batch 64 --data coco.yaml --cfg yolov5s.yaml --weights ''
python -m torch.distributed.launch --nproc_per_node 2 --nnodes 2 --node_rank 1 --master_addr "192.168.1.2" --master_port 1234 train.py --batch 64 --data coco.yaml --cfg yolov5s.yaml --weights ''
nnodes 表示一共有多少机器参与训练
node_rank 表示当前机器的序号从0开始
nproc_per_node 表示每台机器有多少张显卡
master_addr和master_port表示master机器的IP和端口
正常情况,当两台机器都运行完命令,训练就开始了,否则master处于等待状态。
一般情况一台机器GPU的数量等于进程的数量,二般情况是不等于,下面描述的是一般情况
Node 0
Process0 [Global Rank=0, Local Rank=0] -> GPU 0
Process1 [Global Rank=1, Local Rank=1] -> GPU 1
Process2 [Global Rank=2, Local Rank=2] -> GPU 2
Process3 [Global Rank=3, Local Rank=3] -> GPU 3
Node 1
Process4 [Global Rank=4, Local Rank=0] -> GPU 0
Process5 [Global Rank=5, Local Rank=1] -> GPU 1
Process6 [Global Rank=6, Local Rank=2] -> GPU 2
Process7 [Global Rank=7, Local Rank=3] -> GPU 3
这里用Node表述,没有使用Host,Node不限定是物理机器,还有可能是容器例如docker,简单理解就是一个Node节点就是一台机器。
两台机器(节点0和节点1),每个节点上使用2张卡 ,world_size就是 2 * 2 = 4
两台机器(节点0和节点1),每个节点上使用4张卡 ,world_size就是 2 * 4 = 8
一共有3个node(nnodes=3),每个node包含8个GPU,设置nproc_per_node=4,
,world_size就是3 * 4 =12,为什么不是3*8=24呢?因为每个node虽然有8个GPU,但是命令设置只使用其中4个(nproc_per_node=4),有而不使用是不算数的。
world_size的大小=节点数 x 每个节点使用的GPU数量
Global Rank计算范围是在world_size范围之内
Local Rank计算范围是在当前node范围之内
单独说rank,前面没有global或者local,一般指的是global rank
global rank就是在多机多卡时对分布式进程的编号。比如global rank=0 表示0号进程
Local Rank指在一个node内的进程序号
期望程序在访问硬盘时都取访问内存,不访问硬盘
方式1
训练的命令行加入参数 --cache-images
方式2
sudo mount tmpfs /media/data/cache/ -t tmpfs -o size=128G
然后把数据集拷贝到/media/data/cache/,这样/media/data/cache/文件夹的数据全部装入内存
数据集放在这里是临时存放的,计算机重启后会消失。
假如有3台机器,如果每台机器的GPU数量是相同,可以按照上面多机多卡的使用说明来做
模拟出4台机器,每台机器2个GPU。
将4个GPU的机器上程序再拷贝一份,放置到不同的目录。
master的机器,2个GPU
CUDA_VISIBLE_DEVICES='0,1' python -m torch.distributed.launch --nproc_per_node 2 --nnodes 4 --node_rank 0 --master_addr "192.168.1.100" --master_port 5678 train.py --batch 128 --data ./data/coco.yaml --cfg yolov5s.yaml
slave的机器,2个GPU
CUDA_VISIBLE_DEVICES='0,1' python -m torch.distributed.launch --nproc_per_node 2 --nnodes 4 --node_rank 1 --master_addr "192.168.1.100" --master_port 5678 train.py --batch 128 --data ./data/coco.yaml --cfg yolov5s.yaml
slave的机器,4个GPU,使用其中2个GPU
CUDA_VISIBLE_DEVICES='0,1' python -m torch.distributed.launch --nproc_per_node 2 --nnodes 4 --node_rank 2 --master_addr "192.168.1.100" --master_port 5678 train.py --batch 128 --data ./data/coco.yaml --cfg yolov5s.yaml
slave的机器,4个GPU,使用其中2个GPU
CUDA_VISIBLE_DEVICES='2,3' python -m torch.distributed.launch --nproc_per_node 2 --nnodes 4 --node_rank 3 --master_addr "192.168.1.100" --master_port 5678 train.py --batch 128 --data ./data/coco.yaml --cfg yolov5s.yaml
会产生如下错误
情况1
store = TCPStore(master_addr, master_port, world_size, start_daemon, timeout)
RuntimeError: Address already in use
解决方法是 一种是更改下端口号,重新运行命令。另一种时进程里有之前运行的训练进程占用了此地址和端口,可以把该进程结束
查看包含python的进行
ps -aux | grep 进程服务名
ps -aux | grep python
杀死进程
sudo kill 进程号(PID)
sudo kill 1111
情况2
类似如下错误提示
(1) dist.init_process_group(backend='nccl')
(2) NCCL WARN Connect to 192.168.1.2<> failed : No route to host
(3) dist.init_process_group(backend='nccl', init_method='env://') # distributed backend
site-packages/torch/distributed/distributed_c10d.py", line 442, in init_process_group
barrier()
in barrier
work = _default_pg.barrier()
RuntimeError: NCCL error in: /pytorch/torch/lib/c10d/ProcessGroupNCCL.cpp:784, unhandled system error, NCCL version 2.7.8
遇到这种错误需要把nccl日志打开,查看IP绑定网卡是否正确,按照如下操作
(NVIDIA Collective Communications Library (NCCL))
查看网卡
终端执行 ifconfig
找到IP 192.168.1.2 对应的网络
eno1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.1.2 netmask 255.255.255.0 broadcast 192.168.1.255
该示例中是eno1,填写NCCL_SOCKET_IFNAME=eno1
终端执行
export NCCL_DEBUG=INFO
export NCCL_IB_DISABLE=1
export NCCL_SOCKET_IFNAME=eno1
对多网卡的机器一定要设置环境变量NCCL_SOCKET_IFNAME,这样可以减少不必要的错误。
这时候再执行命令就显示日志了,通过日志就能找到是什么地方出现了问题
日志内容
NCCL INFO Call to connect returned Connection refused, retrying
或者
machinename:33983:34116 [2] include/socket.h:403 NCCL WARN Connect to 192.168.1.2<50565> failed : Connection refused
machinename:33983:34116 [2] NCCL INFO bootstrap.cc:95 -> 2
machinename:33983:34116 [2] NCCL INFO bootstrap.cc:309 -> 2
machinename:33983:34116 [2] NCCL INFO init.cc:555 -> 2
machinename:33983:34116 [2] NCCL INFO init.cc:840 -> 2
machinename:33983:34116 [2] NCCL INFO group.cc:73 -> 2 [Async thread]
master的机器运行
nc -l 5678 -v
Listening on [0.0.0.0] (family 0, port 5678)
Connection from 192.168.1.3 39788 received!
slave的机器运行
nc 192.168.1.2 5678
或者执行ping也可以
如果不成功表明问题出在防火墙,把防火墙关闭或者把允许的机器加到防火墙的白名单里
执行添加白名单命令
sudo firewall-cmd --zone=trusted --add-source=192.168.1.2
sudo firewall-cmd --zone=trusted --add-source=192.168.1.3
sudo firewall-cmd --zone=trusted --add-source=192.168.1.4
192.168.1.2是master的机器,把自己的IP也加进去
执行查看trusted区域设置是否正确的命令
firewall-cmd --zone=trusted --list-all
查看防火墙状态
systemctl status firewalld
暂时关闭防火墙
systemctl stop firewalld
永久关闭 firewalld防火墙(重启有效)
systemctl disable firewalld
查看防火墙状态
sudo ufw status
永久关闭防火墙
sudo ufw disable
开启防火墙
sudo ufw enable
当正确执行后slave有如下日志
machinename:37519:37519 [0] NCCL INFO Bootstrap : Using [0]eno1:192.168.1.3<0>
machinename:37519:37519 [0] NCCL INFO NET/Plugin : No plugin found (libnccl-net.so), using internal implementation
machinename:37519:37519 [0] NCCL INFO NCCL_IB_DISABLE set by environment to 1.
machinename:37519:37519 [0] NCCL INFO NET/Socket : Using [0]eno1:192.168.1.3<0>
machinename:37519:37519 [0] NCCL INFO Using network Socket
machinename:37520:37520 [1] NCCL INFO Bootstrap : Using [0]eno1:192.168.1.3<0>
machinename:37520:37520 [1] NCCL INFO NET/Plugin : No plugin found (libnccl-net.so), using internal implementation
machinename:37520:37520 [1] NCCL INFO NCCL_IB_DISABLE set by environment to 1.
machinename:37520:37520 [1] NCCL INFO NET/Socket : Using [0]eno1:192.168.1.3<0>
machinename:37520:37520 [1] NCCL INFO Using network Socket
machinename:37520:38065 [1] NCCL INFO threadThresholds 8/8/64 | 48/8/64 | 8/8/64
machinename:37520:38065 [1] NCCL INFO Trees [0] 2/-1/-1->5->4|4->5->2/-1/-1 [1] 0/-1/-1->5->4|4->5->0/-1/-1
machinename:37519:38064 [0] NCCL INFO threadThresholds 8/8/64 | 48/8/64 | 8/8/64
训练过程中master的机器可以看到训练过程
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。