Ubuntu 18 解决out of memory 问题

2020/3/1 posted in  linux

报错信息:

程序报错:

#程序报错
MemoryError: Unable to allocate 22.4 GiB for an array with shape (54773, 54773) and data type float64

#写入系统日志错误
$ egrep -i 'killed process' /var/log/syslog

Feb 29 23:55:12 iZbp1dfqh2kwqx54njldloZ kernel: [276605.773003] Killed process 9136 (python) total-vm:8352516kB, anon-rss:3838288kB, file-rss:4kB, shmem-rss:0kB

出现原因

使用cosine_similarity(count_matrix, count_matrix)来计算相似性,此时的count_matrix在54773大小,需要组成一个54773 * 54773 * float64大小的向量,需要的内存空间为22.4GB。

但是阿里云购买的服务器只有4v4G,一共的运存只有4G,会造成out of memory溢出。

溢出之后Linux的OOM killer(Out-Of-Memory killer) 会自动的将溢出的进程杀死,所以会直接kill掉该python进行,无法继续执行。

解决步骤1:添加虚拟内存

内存不足的问题,最好的办法是直接升级服务器配置,升为32G的内存的服务器,但是这样所需要的钱还是不少的,特别是按年购买的服务器,没法临时升级。想到最好的方法便是提升虚拟内存,使用硬盘来协助计算。(在需要实时性的环境上还是尽量升级内存)

开始

我这里虚拟了 30G 的容量进行内存扩容(主要是磁盘也不便宜啊),然后 swap 使用的利用率比例为 60,即:当物理内存剩下 60% 时使用 swap 进行交换。

临时配置

临时配置是指重启之后会失效,仅仅只是保持本次开机起作用。

分配文件空间, 建立一个 30G 的 swap 所需的文件空间

dd if=/dev/zero of=/var/blockd.swap bs=1M count=32768

文件 Swap 格式化

mkswap /var/blockd.swap

Swap 激活

swapon /var/blockd.swap

Swap 挂载

打开 /etc/fstab 文件编辑追加以下内容

/var/blockd.swap swap swap default 0 0 

修改 Swap 利用率

sysctl vm.swappiness=60

挂载生效

mount -a

永久配置

永久配置是指重启之后依然保持生效。

分配文件空间
建立一个 30G 的 swap 所需的文件空间

dd if=/dev/zero of=/var/blockd.swap bs=1M count=2048

文件 Swap 格式化

mkswap /var/blockd.swap

Swap 设置自激活

由于 /etc/rc.local 文件会优先于 /etc/fstab 执行,所以在文件 /etc/rc.local 里面增加下面一行命令

swapon /var/blockd.swap

Swap 挂载
打开 /etc/fstab 文件编辑追加以下内容

/var/blockd.swap swap swap default 0 0 

修改 Swap 利用率
编辑 /etc/sysctl.conf 实现永久生效

vm.swappiness=60

重启生效

更多命令

Swap 查看

swapon -s

Swap 关闭

swapoff /var/blockd.swap

查看 Swap 利用率

cat /proc/sys/vm/swappiness

参数解释

vm.swappiness

这个参数主要用来表示物理内存还剩多大比例才开始使用内存交换,本文中设置的值为 60 即当物理内存还剩 60% 时开始进行内存交换;这里有一篇英文相关解释:https://askubuntu.com/questions/969065/why-is-swap-being-used-when-vm-swappiness-is-0

最后
关于为什么阿里云的 ECS 关闭了 Swap ,网上很多观点均是因为阿里云为了保护磁盘而默认进行了关闭(其实交换空间频繁读写实际就是对硬盘的操作),反正我们实现我们想要的就可以了,至于损耗嘛就是官方需要考虑的问题了;关于性能的话根据阿里云的磁盘读写速度文档表明 高效云盘 能够达到 130m/s 的读写速度,比老式机械 70m/s 高了不少,凑合着用吧,如果不满于高效云盘的可以考虑 SSD 那这样的话价格也会不同,自己做一下价格对比吧!!!

解决步骤二:关闭OOM Killer

由于是OOM killer,所以需要关闭OOM Killer 来保证程序不被杀死

sysctl -w vm.overcommit_memory=2

固定:

修改/etc/sysctl.conf文件

添加一行

vm.overcommit_memory=2

注意一定要在扩展了虚拟内存之后再添加这个配置,否则的话,服务器会内存溢出周后hang机。

参考文章:

阿里云 ECS Ubuntu 16.04 创建 Swap 分区

记一次 Linux OOM-killer 分析过程