【问题标题】:memory allocation in numpy.repeatnumpy.repeat 中的内存分配
【发布时间】:2017-08-25 11:43:10
【问题描述】:

我的脚本中有内存泄漏,我将其范围缩小到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 

我有

额外/python-numpy 1.13.1-2 [已安装]

在我的安特戈斯/拱门上

【问题讨论】:

    标签: python numpy memory memory-leaks


    【解决方案1】:

    仅仅因为你使用了del 一个变量并不意味着内存被立即释放。它只是删除变量的名称。 Python的引用计数机制和gc负责释放内存。

    所以为了安全起见,您需要使用 gc.collect 强制 gc 清理可能包含循环引用的所有内容,否则 Python 将“随时”清理这些(可能仅在内存越来越大的情况下)低或一段时间后)。

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

    注意

    del x 不直接调用x.__del__()——前者将x 的引用计数减一,而后者仅在x 的引用计数为零时调用。可能阻止对象的引用计数变为零的一些常见情况包括: 对象之间的循环引用(例如,双向链表或具有父子指针的树数据结构);对捕获异常的函数的堆栈帧上的对象的引用(存储在sys.exc_info()[2] 中的回溯使堆栈帧保持活动状态);或对堆栈帧上的对象的引用,该对象在交互模式下引发了未处理的异常(存储在sys.last_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

    【讨论】:

    • 是的,忘了 gc,我现在看到它适用于示例代码。不幸的是,在我的主脚本中不起作用,但我想还有一些链接留在某处
    • @gavlig 仍然可能是引用或内存泄漏,我只是说依靠del 清理内存是错误的假设。如果您真的怀疑内存泄漏,您应该使用 valgrind 之类的工具或将其报告给 NumPy 开发人员。 :)
    • @gavlig 请注意,视图使原始数组保持活动状态,因此如果您有 1000x1000 数组的 2x2 视图并保持视图,它将保持 1000x1000 数组活动!这是发生在我身上好几次的事情。在这些情况下,您可以简单地copy 视图来删除原始链接。但这只是在不知道您的代码的情况下的猜测——您可能需要自己检查一下。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    • 2014-06-27
    相关资源
    最近更新 更多