目录
一、异常问题
1.segementation fault(core dump)
2.Illegal instruction(core dumped)
3.死锁
4.掉卡
二、通用方法
1.查看重启记录
2.系统性能监控
3.后台执行命令
4.异常日志
三、深度学习技术
1.普通网络改DDP训练,单机多卡,pytorch
四、专业内容方法
1.微调diffusion类模型
本文记录一些在使用linux服务器进行深度学习时遇到的问题。
本文主要以ssh远程连接方式操作Ubuntu20.04,使用了anaconda配置环境。
显卡为两张4090显卡,单卡24G显存。
没有说明的代码段均为bash代码。
发生的场景较多,推测一般为内存问题,设置内存中栈大小(stack size)上限为无限 ,ulimit -a查看当前上限,-s unlimited设置,该设置为临时设置,只在当前会话生效,会话断开、系统重启等之后应重新设置。另有永久修改办法,需修改系统配置文件。
ulimit -a
ulimit -s unlimited
非法指针,尝试在dataloader的参数num_workers改用较小值:2,4,8,等。
首先应确定死锁不是我们代码的问题。使用pytorch库发生死锁,可能与图片的读取(不论是cv2还是PIL读取方式)、内存分配等问题有关,这是深度学习框架的底层工作造成的。通过MKL库指令,指定单线程操作。
尝试使用单线程的指令,避免死锁。分布式训练同样可以使用,并不会阻止DDP训练。
MKL_NUM_THREAD=1 python xx.py
MKL_NUM_THREAD=1 python -m torch.distributed.launch --nproc_per_node 2 xx.py
另外服务器长时间运行发生死锁的概率要大于刚刚重启时。linux 死锁有两种分别为soft lock和hard lock。死锁发生后会向会话不断返回死锁信息,直到彻底死机,ssh断开。
深度学习训练过程,卡死,失去控制。表现:
解决方法:重启。启动后,同时使用规定额定功率上线和启用持久模式(Persistence-M)两方法重新训练:
nvidia-smi #可查看最大功率和目前是否开启持久模式
sudo nvidia-smi -pl 450 #根据电源调整,这里为450W
sudo nvidia-smi -pm 1 #开启持久模式
tip:为什么叫掉卡?
在var/log/message中可以注意到有类似如下错误提示,GPU“掉”下了bus(总线)。
NVRM: GPU 0000:01:00.0: GPU has fallen off the bus.
/var/log/wtmp记录每个用户登录、注销及系统的启动、停机的事件。(ssh会话的开启与结束),无sudo权限也可读取。注意该文件为二进制文件,不应使用vim。
last指令,用于直接读取该文件,并把该文件记录登录的用户名,全部显示出来。
查询近十行wtmp内容和查询关机:
last -10 -f /var/log/wtmp
last -x -F shutdown
last的可选参数 -x 为显示系统关机,重新开机,以及执行等级的改变等信息。其他地,-10 为10行,-f 参数指定读取的文件,-F 为指定显示完整的时间。
多人共用服务器时,应注意观察服务器性能参数:
watch -n 2 nvidia-smi #监控GPU情况,2s刷新一次
top #较为全面的系统监控,可以查看进程、内存、cpu的相关情况
#进入top指令界面后,键入数字1,查看各cpu情况
watch sensors #查看各个温度传感器的情况
nohup不挂断地运行命令,可以在命令执行过程中,通过当前会话进行其他操作。用>重定向输出(默认为nohup.out,建议tail命令查看)。
注意:不以&结尾时,如果关闭会话,进程会停止。
长时间跑代码建议使用带&的nohup语句后,使用exit命令推出当前会话。(之后可以在新建对话查看输出是否正常)
nohup sh xxx.sh >nohup.out &
exit #退出对话
nohup python xxx.py &
tail -n 10 nohup.out #查看最后十行的输出
/var/log/messages:系统启动后的信息和错误日志。
ubuntu默认没有启动记录,启动记录方法:vim指令打开/etc/rsyslog.conf文件,取消关于/var/log/messages这一行的注释。之后重启rsyslog服务:
/bin/systemctl restart rsyslog.service
DDP(DistributedDataParallel)分布式并行训练是适于单机多卡的一种训练方式,在单机多卡训练中优于DP。本人起初对于DDP操作无感,因为认为个人领域内不必过于压榨GPU。但逐渐意识到作为一种高效训练手段,仍推荐在各类项目中使用,提高效率。目前在许多领域,尤其是关于深度学习与其他学科的交叉领域,论文代码作者水平往往有限,使用DDP方式训练的并不是很多。
将普通的pytorch框架训练代码修改可以使用DDP训练方式主要有以下步骤
#python
#train.py
#-----------------------------
# 1.加入关于DDP的库
import torch.distributed as dist
from torch.nn.parallel import DistributedDataParallel as DDP
# 2.添加代码,需要导入os库
import os
rank = int(os.environ["RANK"])
local_rank = int(os.environ["LOCAL_RANK"])
torch.cuda.set_device(rank % torch.cuda.device_count())
dist.init_process_group(backend="nccl")
# 3.神经网络加载的区别
self.net = unet.UNet().to(self.device) #如果这是原始的加载方法,unet保存在同级的文件中
##修改,在模型加载后加入这一行代码,根据原始代码结构,将参数传入即可
self.net = DDP(self.net, device_ids=[local_rank], output_device=local_rank)
#4.数据加载的修改
在参数中写明显卡数量,或者使用CUDA_VISIBLE_DEVICES指定编号,命令:
python -m torch.distributed.launch --nproc_per_node 2 main.py
#指定显卡号,添加CUDA_VISIBLE_DEVICES
CUDA_VISIBLE_DEVICES=1,3,5,7 python -m torch.distributed.launch --nproc_per_node 4 main.py
可能的问题:RuntimeError: The server socket has failed to listen on any local network address. The server socket has failed to bind to [::]:29500 (errno: 98 - Address already in use)
lsof -i:29500 #29500是DDP默认端口,该命令可获得占用端口的进程的pid
kill -9 pid #结束占用端口的进程,注意替换pid