Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
隐藏的Python内存泄漏_Python_Pandas_Numpy_Memory Leaks_Jupyter Notebook - Fatal编程技术网

隐藏的Python内存泄漏

隐藏的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

在下面的代码中,在迭代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, 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您能帮忙吗?谢谢添加代码。我会看一看,但是的,这看起来像是一个内存泄漏线的某个地方。。。