隐藏的Python内存泄漏
在下面的代码中,在迭代c1=0和迭代c1=60之间,内存使用量大约增加了1G。你能帮我找出漏洞吗隐藏的Python内存泄漏,python,pandas,numpy,memory-leaks,jupyter-notebook,Python,Pandas,Numpy,Memory Leaks,Jupyter Notebook,在下面的代码中,在迭代c1=0和迭代c1=60之间,内存使用量大约增加了1G。你能帮我找出漏洞吗 # M = 1000, N=18000 # data is a pandas dataframe with N rows and M columns (it is already loaded when this code begins). mymat = np.zeros((M,M,N), dtype=bool) table = pd.Series(index=data.index, d
# M = 1000, N=18000
# data is a pandas dataframe with N rows and M columns (it is already loaded when this code begins).
mymat = np.zeros((M,M,N), dtype=bool)
table = pd.Series(index=data.index, data=np.array(range(N)))
data_std = data.std(axis=1)
for c1 in range(M):
for c2 in range(M):
if c1!=c2:
mymat[c1,c2,list(
table.loc[data.index[data.iloc[:,c1]-data.iloc[:,c2]>data_std]])] = True
这实际上似乎根本不是内存泄漏,而是一个优化NumPy或您的操作系统提供给您的。(可能是您的操作系统,考虑到您的代码在原始问题中的工作方式存在特定于操作系统的差异。) 下面是一个简化的
示例.py
——基本思想是相同的
将numpy导入为np
导入操作系统
导入psutil
process=psutil.process(os.getpid())
def打印_存储器(信息):
rss=进程.memory_info().rss
打印(f“{message:30s}{rss//1024:7d}kb”)
M=N=1000
打印内存(“开始”)
#mymat=np.zero((M,M,N),dtype=bool)
#mymat=(np.random.random((M,M,N))>0.5)
打印内存(“已生成”)
对于范围(M)内的c1:
如果c1%100==0:
打印内存(f'迭代{c1}')
对于范围(M)内的c2:
mymat[c1,c2[1,2,3]]=True
打印存储(f'end')
打印(mymat.n字节、mymat.d类型、mymat.shape)
在启用第一个mymat
行的情况下运行此命令(即生成零)将打印输出
$ python3 example.py
start 23552kb
generated 23564kb
iteration 0 23564kb
iteration 100 121340kb
iteration 200 218996kb
iteration 300 316652kb
iteration 400 414320kb
iteration 500 511976kb
iteration 600 609632kb
iteration 700 707288kb
iteration 800 804944kb
iteration 900 902600kb
end 1000256kb
1000000000 bool (1000, 1000, 1000)
因此,您可以看到,“生成”1000 x 1000 x 1000阵列实际上并不占用1GB的内存Numpy的nbytes
说它占用了1GB的内存,但当它开始填充非零数据时,就会发生分配
使用第二个选项运行它,生成随机数据,结果如下:
$ python3 example.py
start 23404kb
generated 1000004kb
iteration 0 1000004kb
iteration 100 1000140kb
iteration 200 1000148kb
iteration 300 1000164kb
iteration 400 1000164kb
iteration 500 1000164kb
iteration 600 1000164kb
iteration 700 1000164kb
iteration 800 1000164kb
iteration 900 1000164kb
end 1000164kb
1000000000 bool (1000, 1000, 1000)
正如您所看到的,所有的内存都是立即分配的,而在循环过程中出现的少量内存增加实际上是一个舍入错误,可能只是由于常规的GC分配。(np.ones()
具有相同的行为。)
至于您原来的1000*1000*18000阵列,如果您确实需要填充所有阵列,那么您最终将需要
>>> np.zeros((1000, 1000, 18000), dtype=bool).nbytes
18000000000
18千兆字节的内存。(这也表明,Numpy没有布尔数组的特定压缩数据类型;每个布尔数组占用一个字节,而不仅仅是一位。这可能是由于性能原因。)如果不查看代码或至少不了解它的实际功能,就很难判断。我添加了对代码井的描述,如果内存使用量持续增加,则表示您在某处泄漏了一些内存(例如,将变量的副本保留在周围等)。@AKX您能帮忙吗?谢谢添加代码。我会看一看,但是的,这看起来像是一个内存泄漏线的某个地方。。。