目标检测 YOLOv5 - 多机多卡训练

本文详细介绍了如何在YOLOv5中利用CUDA_VISIBLE_DEVICES环境变量配置GPU,包括多机多卡训练的步骤,如master和slave机器的命令行设置。此外,还提供了处理异常情况的技巧,如网络连接问题、防火墙设置等,确保分布式训练的顺利进行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目标检测 YOLOv5 - 多机多卡训练

flyfish

环境:

Python>=3.6.0 
PyTorch>=1.7
YOLOv5:v5

1 CUDA_VISIBLE_DEVICES环境变量

通过设置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'

2 多机多卡的使用

分两种类型机器一个master,其他都是slave

master机器运行的命令
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 ''
第R台slave机器运行的命令
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 ''

假设有两台机器,每台机器都有两张卡

实际master机器运行的命令
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 ''
实际第R台slave机器运行的命令
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内的进程序号

3 快速训练的方案

3.1 快速读取数据

期望程序在访问硬盘时都取访问内存,不访问硬盘
方式1
训练的命令行加入参数 --cache-images
方式2

sudo mount tmpfs /media/data/cache/ -t tmpfs -o size=128G

然后把数据集拷贝到/media/data/cache/,这样/media/data/cache/文件夹的数据全部装入内存
数据集放在这里是临时存放的,计算机重启后会消失。

3.2 多台机器,不同GPU数量的使用

假如有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

4 异常情况的处理

会产生如下错误
情况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
4.1 查看日志

遇到这种错误需要把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]
4.2 查看两台机器是否互通

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
4.3 firewalld防火墙操作

查看防火墙状态

systemctl status firewalld

暂时关闭防火墙

systemctl stop firewalld

永久关闭 firewalld防火墙(重启有效)

systemctl disable firewalld 
4.4 ufw防火墙操作

查看防火墙状态

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的机器可以看到训练过程

YOLov5是一个流行的目标检测模型,可以使用进行训练以加快训练速度。下面是使用YOLov5进行单训练的步骤: 1. 准备数据集:首先,你需要准备用于目标检测的数据集。确保数据集已经按照YOLov5的要求进行了标注和划分。 2. 安装依赖:确保你已经安装了PyTorch和其他相关依赖。 3. 下载YOLov5代码:你可以从YOLov5的官方GitHub仓库下载最新的代码。 4. 配置训练参数:在YOLov5代码的文件中,你可以找到一个名为"hyp.yaml"的文件,其中包含了训练的超参数设置。根据你的需求进行相应的配置,例如学习率、批大小等。 5. 设置训练:打开"train.py"文件,找到以下代码行: ``` # 自动选择最佳GPU gpus = [0] # 默认使用单个GPU ``` 将其修改为: ``` # 使用个GPU gpus = [0, 1, 2, 3] # 选择你想要使用的GPU编号 ``` 6. 启动训练:在终端中运行以下命令开始训练: ``` python train.py --batch-size {batch_size} --cfg {config_file} --data {data.yaml} --multi-scale --img {image_size} --device {device} ``` 其中,{batch_size}是每个GPU的批大小,{config_file}是模型配置文件路径,{data.yaml}是数据集配置文件路径,{image_size}是输入图像的尺寸,{device}是使用的设备(例如cuda:0)。 请注意,你可能需要根据你的具体环境和需求进行适当的调整。训练通常可以显著提高训练速度,但也可能会增加训练过程中的内存消耗。确保你的硬件和环境能够支持训练
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二分掌柜的

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值