前言
写了一个循环函数,每次循环使用一个wandb.run记录数据。 最后报错 OSError: [Errno 24] Too many open files 。 国内用wandb的人好像还不是很多…隔壁tensorboard的为主。 自食其力。
问题探索
可以用psutil库持续跟踪进程的句柄和描述符数量。
import psutil
def num_open_files():
s = psutil.Process()
num_open_files = len(s.open_files())
num_file_descriptions = s.num_fds()
return num_open_files ,num_file_descriptions
在我跑的代码中, 这个num open files的2,在wandb.finish()之后就清0了。 但是num_fds持续增加。 每过一个循环+4。
可以看出来问题还是在file description的数量上。这样一直增加下去,达到上限可不就报错了么。
通过命令可以查看当前进程(11448)下的所有文件描述符。
ls -l \proc\11448\fd
从这个图已经能看出来为什么每个循环num_fd会 +4了。 每个循环里,都会打开2个描述符,指向 ‘/dev/pts/92’ 。 然后打开2个描述符,指向2个wandb上传管道。 这样一共是4个fd。 符合观察。
python里的文件描述符需要显式关闭
我遇到的这个问题, 归根结底是wandb会持续打开新的连接,创建新的管道,向服务器传数据。 但python没有很好的自动回收机制处理这些句柄。
注意:python打开的文件描述符需要显式进行关闭。
这是python的特性决定的。 一般的文件操作中,我们用with scope的话,会自动关闭这个fd。 或者用os.close(file)自己关闭。
但wandb没有写好这个功能。只打开,不关闭。 (去提issue)
解决方案
在官方解决这个问题之前,我们可以试着增加系统对文件描述符的限制。 linux默认一般是1024,每个循环+4,那么最多256个循环就满了。
软硬限制
硬限制是实际的限制,而软限制,是warnning限制,只会做出warning
分析句柄数
分析句柄数,查找原因,这是解决问题最根本的办法。那么如何分析那,就需要用到lsof这个命令了(关于这个命令大家可以在网上学习学习)。
1 统计各进程打开句柄数:lsof -n|awk ‘{print $2}’|sort|uniq -c|sort -nr 2 统计各用户打开句柄数:lsof -n|awk ‘{print $3}’|sort|uniq -c|sort -nr 3 统计各命令打开句柄数:lsof -n|awk ‘{print $1}’|sort|uniq -c|sort -nr
文件打开数量
Check Hard/Soft Limit in Linux
ulimit -Hn ulimit -Sn
查看
ulimit -n
设置2个一起提高(直到下次reboot前有效)
ulimit -SHn 65535
写入文件
vim /etc/security/limits.conf 加两行 soft nofile 65535 hard nofile 65535
文件描述符数量
全局设置文件描述符数量 Check System wide File Descriptors Limits in Linux
整个系统所有用户的最大打开数量
cat /proc/sys/fs/file-max 26357916
可以直接vim
vim /proc/sys/fs/file-max 加一行
sysctl -w fs.file-max=500000
vi /etc/sysctl.conf
fs.file-max=500000
sysctl -p
为单用户设置文件描述符数量
vi /etc/security/limits.conf
//https://www.cnblogs.com/feng0815/p/8620564.html //https://www.tecmint.com/increase-set-open-file-limits-in-linux/
|