Pytorch分布式训练遇到的问题及解决方案

问题背景:

实验室新买了两张4090D,在装好机器后出现了若干问题,主要包括Xorg占用显卡显存、分布式训练报错、显存分配等问题,本人主要的工作是在Pytracking框架中实现,记录一下问题及解决方案,希望能帮助遇到相同问题的朋友们。

  • 服务器系统:Ubuntu
  • GPU:2张 nvidia-4090D
  • CPU:i7-13700K
  • 主板:华硕

问题描述

  • 问题1:独立显卡显存被占用(资源浪费)

    装好显卡驱动后,使用 nvidia-smi 命令检查,发现显存被Xorg占用约400M。
    排查及解决方案:
    因为之前在3090的机器上跑实验的时候,未存在上述显存占用现象,所以认为该情况是可以避免的,可以节约显存资源。
    Xorg是Linux的GUI图形化进程,可以将其部署在核显上,我使用的13700K是带核显的,CPU没有核显的只能将Xorg部署在独立显卡上
    有的主板是默认禁用核显的,以使用的华硕主板为例:需要在BIOS菜单中,找到Advanced、Chipset、Northbridge或IntegratedPeripherals的子菜单, 在这个部分,找到InternalGraphicsModeSelect,将其从禁用状态改为Auto或Enabled,以启用核显功能。
    网上的教程说可以通过命令或配置文件将Xorg重新部署,但是我没有成功,并且将图像界面也搞崩溃了。最后,简单粗暴的重装系统了,先用核显部署完Xorg,再装独立显卡驱动,装显卡驱动的时候一定别选将Xorg转移部署的选项!问题解决。

  • 问题2:启动分布式训练报错及显存分配不均衡
    单卡训练正常,多卡训练报错,多卡训练显存占用有问题(一个卡占满一个卡不占用/一张卡占用多一张卡占用少)。
    排查及解决方案:
    以下是我的代码中启动分布式训练的命令,其中 torch.distributed.launch 在2.0版本被弃用,之后的版本都是用 torch.distributed.run 启动分布式训练。
    直接使用launch或直接将launch改成run都会存在错误,主要错误都是由 local_rank 未正常分配 引起的。
    --local_rank 是获取当前进程在本机上的rank,一般是动态获取的。在官方的说明文档中对此参数有详细解释,“–local_rank"这个命令行参数是必须声明的,但不由用户填写,是由pytorch自动填写的。如果用户声明了这个参数,则会覆盖掉pytorch为用户生成的值,就会产生错误。

elif args.mode == "multiple":
        train_cmd = "python -m torch.distributed.launch --nproc_per_node %d --master_port %d lib/train/run_training.py " \
                    "--script %s --config %s --save_dir %s --use_lmdb %d --script_prv %s --config_prv %s --use_wandb %d " \
                    "--distill %d --script_teacher %s --config_teacher %s" \
                    % (args.nproc_per_node, random.randint(10000, 50000), args.script, args.config, args.save_dir, args.use_lmdb, args.script_prv, args.config_prv, args.use_wandb,
                       args.distill, args.script_teacher, args.config_teacher)

在我的代码中并未声明该参数,这就是引起错误的原因。

 elif args.mode == "multiple":
        train_cmd = "CUDA_VISIBLE_DEVICE=0,1 python -m torch.distributed.launch --nproc_per_node %d --master_port %d --use-env lib/train/run_training.py " \
                    "--script %s --config %s --save_dir %s --use_lmdb %d --script_prv %s --config_prv %s --use_wandb %d " \
                    "--distill %d --script_teacher %s --config_teacher %s " \
                    % (args.nproc_per_node, random.randint(10000, 50000), args.script, args.config, args.save_dir,
                       args.use_lmdb, args.script_prv, args.config_prv, args.use_wandb,
                       args.distill, args.script_teacher, args.config_teacher)

以上是修改后的代码,其中 CUDA_VISIBLE_DEVICE=0,1 能解决程序对显存占用不均衡的问题,添加了 --use_env参数,声明了此参数后,pytorch会将当前进程在本机上的rank自动添加到环境变量 LOCAL_RANK 中,并不再添加到 args.local_rank
上述改动在 torch.distributed.launch 可以生效,但是在 torch.distributed.run--use_env 已经被废弃,用户中只能从LOCAL_RANK中获取当前进程在本机上的rank,所以需要加入以下代码。

args.local_rank = int(os.environ['LOCAL_RANK'])

最终,我是继续使用 torch.distributed.launch 启动分布式训练,在命令行中加入 CUDA_VISIBLE_DEVICE=0,1--use_env ,同时加入了从环境变量中获取local_rank的代码行,解决问题。

  • 问题3:分布式训练对CPU内核占用
    解决上述两个问题后,我的实验就能正常跑起来了,过程中也没有问题。但是实验室后续又组了一台新的4090D双卡机器,根据上述过程能跑起来分布式训练,但是同门反应分布式训练速度明显比之前的单张4090变慢了。
    排查及解决方案:
    在使用 htop 检查时,发现CPU只有两个核跑满,这部分实际应该受num_worker控制。在调试过程中,多次更改num_worker值无效后,在隔壁组师兄的帮助下最终将问题定位在 run_training.py中,import cv 应该在 import torch 和 import numpy之后,修改完num_worker就能正常控制CPU内核分配了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值