numpy.repeat中的内存分配

时间:2017-08-25 11:43:11

标签: python numpy memory memory-leaks

我的脚本中有内存泄漏,我将其缩小到np.repeat。从理论上讲,如果我有一些np.array具有自己的指针arr并且我创建了一个arr_repeated = arr.repeat(10, axis = 0),然后在它们两个上做del,那么内存是否应该占用他们被释放了吗?

我正在检查:

psutil.Process(os.getpid()).memory_info().rss 

更具体地说,以下代码中memory_beforememory_after会有所不同吗?

arr = np.array([[1,2,3,...], [...], [...]])
arr_repeated = arr.repeat(10, axis = 0)

memory_before = psutil.Process(os.getpid()).memory_info().rss 

del arr
del arr_repeated

memory_after = psutil.Process(os.getpid()).memory_info().rss 

我有

  

extra / python-numpy 1.13.1-2 [已安装]

在我的antergos / arch

1 个答案:

答案 0 :(得分:0)

仅仅因为您使用del变量并不意味着内存会立即释放。它只删除变量的名称。 Pythons引用计数机制,gc负责释放内存。

因此,为了安全起见,您需要使用gc.collect强制gc清除可能包含循环引用的所有内容,否则Python将“随时”清除这些内容(可能只有如果记忆力降低或在一定时间后)。

例如the documentation about __del__包含此注释:

  

注意

     

del x不直接调用x.__del__() - 前者将x的引用计数减1,后者仅在x引用计数时调用达到零。可能阻止对象的引用计数变为零的一些常见情况包括:对象之间的循环引用(例如,双向链表或具有父指针和子指针的树数据结构);对捕获异常的函数的堆栈帧上的对象的引用(存储在sys.exc_info()[2]中的回溯使堆栈帧保持活动状态);或者在交互模式下引发未处理异常的堆栈帧上的对象的引用(存储在sys.last_traceback中的回溯使堆栈帧保持活动状态)。第一种情况只能通过明确打破周期来弥补;第二个可以通过释放对traceback对象不再有用的引用来解决,第三个可以通过将None存储在sys.last_traceback中来解决。启用循环垃圾收集器时会检测并清除循环引用(默认情况下处于打开状态)。有关此主题的更多信息,请参阅gc模块的文档。

import numpy as np
import psutil
import os
import gc

arr = np.array([list(range(10000)), list(range(10000)), list(range(10000))])
arr_repeated = arr.repeat(10, axis = 0)

gc.collect()
memory_before = psutil.Process(os.getpid()).memory_info().rss

del arr
del arr_repeated

gc.collect()
memory_after = psutil.Process(os.getpid()).memory_info().rss

请注意,gc还有一个设置来检测泄漏:gc.set_debug(gc.DEBUG_LEAK)不确定它是如何正常工作的,但值得一试,而不是使用psutil