报错信息:
程序报错:
#程序报错
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机。
参考文章: