SLURM Python脚本在循环中积累内存
我正在SLURM scheduler for HPC上运行一个简单的python脚本。 它读取一个数据集(约6GB),并打印和保存部分数据的图像。其中有几个数据文件,所以我使用循环进行迭代,直到我从每个文件中绘制完数据 然而,由于某些原因,每个循环中的内存使用量都会增加。我已经使用getsizeof()映射了变量,但它们似乎不会随着迭代而改变。所以我不确定这个内存“泄漏”是从哪里来的 这是我的剧本:SLURM Python脚本在循环中积累内存,python,memory-leaks,out-of-memory,slurm,Python,Memory Leaks,Out Of Memory,Slurm,我正在SLURM scheduler for HPC上运行一个简单的python脚本。 它读取一个数据集(约6GB),并打印和保存部分数据的图像。其中有几个数据文件,所以我使用循环进行迭代,直到我从每个文件中绘制完数据 然而,由于某些原因,每个循环中的内存使用量都会增加。我已经使用getsizeof()映射了变量,但它们似乎不会随着迭代而改变。所以我不确定这个内存“泄漏”是从哪里来的 这是我的剧本: import os, psutil import sdf_helper as sh import
import os, psutil
import sdf_helper as sh
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as plticker
plt.rcParams['figure.figsize'] = [6, 4]
plt.rcParams['figure.dpi'] = 120 # 200 e.g. is really fine, but slower
from sys import getsizeof
for i in range(5,372):
plt.clf()
fig, ax = plt.subplots()
#dd gets data using the epoch specific SDF file reader sh.getdata
dd = sh.getdata(i,'/dfs6/pub/user');
#extract density data as 2D array
den = dd.Derived_Number_Density_electron.data.T;
nmin = np.min(dd.Derived_Number_Density_electron.data[np.nonzero(dd.Derived_Number_Density_electron.data)])
#extract grid points as 2D array
xy = dd.Derived_Number_Density_electron.grid.data
#extract single number time
time = dd.Header.get('time')
#free up memory from dd
dd = None
#plotting
plt.pcolormesh(xy[0], xy[1],np.log10(den), vmin = 20, vmax = 30)
cbar = plt.colorbar()
cbar.set_label('Density in log10($m^{-3}$)')
plt.title("time: %1.3e s \n Min e- density: %1.2e $m^{-3}$" %(time,nmin))
ax.set_facecolor('black')
plt.savefig('D00%i.png'%i, bbox_inches='tight')
print("dd: ", getsizeof(dd))
print("den: ",getsizeof(den))
print("nmin: ",getsizeof(nmin))
print("xy: ",getsizeof(xy))
print("time: ",getsizeof(time))
print("fig: ",getsizeof(fig))
print("ax: ",getsizeof(ax))
process = psutil.Process(os.getpid())
print(process.memory_info().rss)
输出
Reading file /dfs6/pub/user/0005.sdf
dd: 16
den: 112
nmin: 32
xy: 56
time: 24
fig: 48
ax: 48
8991707136
Reading file /dfs6/pub/user0006.sdf
dd: 16
den: 112
nmin: 32
xy: 56
time: 24
fig: 48
ax: 48
13814497280
Reading file /dfs6/pub/user/0007.sdf
dd: 16
den: 112
nmin: 32
xy: 56
time: 24
fig: 48
ax: 48
18648313856
#!/bin/bash
#SBATCH -p free
#SBATCH --job-name=epochpyd1
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --mem-per-cpu=20000
#SBATCH --mail-type=begin,end
#SBATCH --mail-user=**
module purge
module load python/3.8.0
python3 -u /data/homezvol0/user/CNTDensity.py > density.out
/data/homezvol0/user/CNTDensity.py:21: RuntimeWarning: divide by zero encountered in log10
plt.pcolormesh(xy[0], xy[1],np.log10(den), vmin = 20, vmax = 30)
/export/spool/slurm/slurmd.spool/job1910549/slurm_script: line 16: 8004 Killed python3 -u /data/homezvol0/user/CNTDensity.py > density.out
slurmstepd: error: Detected 1 oom-kill event(s) in step 1910549.batch cgroup. Some of your processes may have been killed by the cgroup out-of-memory handler.
SLURM输入
Reading file /dfs6/pub/user/0005.sdf
dd: 16
den: 112
nmin: 32
xy: 56
time: 24
fig: 48
ax: 48
8991707136
Reading file /dfs6/pub/user0006.sdf
dd: 16
den: 112
nmin: 32
xy: 56
time: 24
fig: 48
ax: 48
13814497280
Reading file /dfs6/pub/user/0007.sdf
dd: 16
den: 112
nmin: 32
xy: 56
time: 24
fig: 48
ax: 48
18648313856
#!/bin/bash
#SBATCH -p free
#SBATCH --job-name=epochpyd1
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --mem-per-cpu=20000
#SBATCH --mail-type=begin,end
#SBATCH --mail-user=**
module purge
module load python/3.8.0
python3 -u /data/homezvol0/user/CNTDensity.py > density.out
/data/homezvol0/user/CNTDensity.py:21: RuntimeWarning: divide by zero encountered in log10
plt.pcolormesh(xy[0], xy[1],np.log10(den), vmin = 20, vmax = 30)
/export/spool/slurm/slurmd.spool/job1910549/slurm_script: line 16: 8004 Killed python3 -u /data/homezvol0/user/CNTDensity.py > density.out
slurmstepd: error: Detected 1 oom-kill event(s) in step 1910549.batch cgroup. Some of your processes may have been killed by the cgroup out-of-memory handler.
SLURM输出
Reading file /dfs6/pub/user/0005.sdf
dd: 16
den: 112
nmin: 32
xy: 56
time: 24
fig: 48
ax: 48
8991707136
Reading file /dfs6/pub/user0006.sdf
dd: 16
den: 112
nmin: 32
xy: 56
time: 24
fig: 48
ax: 48
13814497280
Reading file /dfs6/pub/user/0007.sdf
dd: 16
den: 112
nmin: 32
xy: 56
time: 24
fig: 48
ax: 48
18648313856
#!/bin/bash
#SBATCH -p free
#SBATCH --job-name=epochpyd1
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --mem-per-cpu=20000
#SBATCH --mail-type=begin,end
#SBATCH --mail-user=**
module purge
module load python/3.8.0
python3 -u /data/homezvol0/user/CNTDensity.py > density.out
/data/homezvol0/user/CNTDensity.py:21: RuntimeWarning: divide by zero encountered in log10
plt.pcolormesh(xy[0], xy[1],np.log10(den), vmin = 20, vmax = 30)
/export/spool/slurm/slurmd.spool/job1910549/slurm_script: line 16: 8004 Killed python3 -u /data/homezvol0/user/CNTDensity.py > density.out
slurmstepd: error: Detected 1 oom-kill event(s) in step 1910549.batch cgroup. Some of your processes may have been killed by the cgroup out-of-memory handler.
据我所知,一切似乎都在运转。不确定什么会占用超过20GB的内存
编辑
所以我开始从下到上注释循环的各个部分。现在很明显,普科洛梅什是罪魁祸首
我添加了():
直到最后,但无论发生什么,记忆都在不断攀升。我完全不知道发生了什么事。您走的是正确的道路,可以看到每次迭代累积了多少内存。调试的下一步是想一想这些记忆可能在哪里积累的假设,以及测试这些假设的方法 每次迭代后,一个保持在内存中的变量是
den
。您可以排除这些假设(从而缩小问题范围),方法是通过dd=None
清除这些变量,或者通过del dd
删除它们,或者将循环体的一部分移动到子例程中,这样当这些子例程返回时,一些变量就会消失。(分解出子例程也可以使这些部分更易于重用和测试。)这种技术可以排除问题的一些可能原因,但我不希望这些变量赋值在迭代过程中积累内存,如果代码在每次迭代时向dict
或列表添加数据,就会积累内存
另一个假设是,matplotlib
中的状态累积未被plt.clf()
清除,或者在sdf\u helper
中的状态累积。我对这些库了解不够,无法提供直接的见解,但它们的文档应该说明如何清除状态。即使不知道如何弄清它们的状态,我们也可以想出方法来检验这些假设。例如,注释掉plt
调用或至少注释掉数据密集型调用,然后查看内存是否仍在累积
你可能会想到比我更多的假设。首先头脑风暴假设是一种很好的方法,因为其中一个假设可能是明显的最佳候选,或者其中一个假设可能比其他假设更容易测试
请注意,积累内存可能有多个原因,在这种情况下,修复一个原因将减少内存积累,但无法修复它。因为你在测量记忆积累,你就能检测到这一点。在许多调试情况下,我们看不到多个原因对问题(如片状结果)的增量贡献,因此另一种方法是删除所有可能导致问题的原因,然后一次添加一个
添加内容
现在您已经将问题缩小到pcolormesh
,下一步是阅读有关matplotlib和pcolormesh
如何使用内存的or教程。此外,通过web搜索pcolormesh内存泄漏
可以找到有关此问题的特定提示
最简单的尝试是添加对ax.cla()
的调用以清除轴,如中所示
您可以从pyplot切换到matplotlib的面向对象接口,该接口不会保留太多全局状态。相反,我认为pyplot
保留了fig
和ax
,在这种情况下,释放变量不足以释放它们的对象
显然imshow
请注意,其中建议只创建一次pcolormesh
,然后在每次循环迭代中设置其数据——您可以在每次迭代中执行mesh=plt.pcolormesh(…)
一次,然后执行类似mesh.set\u数组(np.log10(den))
的操作吗?它还建议您致电cla()
感谢您的回复!我做了一些编辑。看来普科洛梅什是罪魁祸首。我尝试了其他方法来删除或释放该图(),但内存保持不变climing@ddwong我通过网络搜索和查看Matplotlib文档,添加了一些关于pcolormesh内存保留的注释。你可能需要比我更深入地研究那些文档。