循环加载npz文件会导致内存溢出(取决于文件
list 长度)。

以下内容似乎无济于事

  • 删除将数据存储在文件中的变量。
  • 使用mmap。
  • 调用gc.collect()(垃圾回收)。

  • 下面的代码应重现此现象:
    import numpy as np
    
    # generate a file for the demo
    X = np.random.randn(1000,1000)
    np.savez('tmp.npz',X=X)
    
    
    # here come the overflow:
    for i in xrange(1000000):
        data = np.load('tmp.npz')
        data.close()  # avoid the "too many files are open" error
    

    在我的实际应用程序中,循环遍历文件列表,并且溢出超过24GB的RAM!
    请注意,这是在ubuntu 11.10和numpy v上都尝试过的
    1.5.1和1.6.0

    我已经在numpy ticket 2048中提交了一份报告,但这可能引起了广泛的关注,因此我也将其发布在这里(此外,我不确定这是一个错误,但可能是由于我的编程错误造成的)。

    解决方案(通过HYRY):

    命令
    del data.f
    

    应该在命令之前
    data.close()
    

    有关更多信息和找到解决方案的方法,请阅读下面的HYRY友善答案

    最佳答案

    我认为这是一个错误,也许我找到了解决方案:调用“del data.f”。

    for i in xrange(10000000):
        data = np.load('tmp.npz')
        del data.f
        data.close()  # avoid the "too many files are open" error
    

    发现这种内存泄漏。您可以使用以下代码:
    import numpy as np
    import gc
    # here come the overflow:
    for i in xrange(10000):
        data = np.load('tmp.npz')
        data.close()  # avoid the "too many files are open" error
    
    d = dict()
    for o in gc.get_objects():
        name = type(o).__name__
        if name not in d:
            d[name] = 1
        else:
            d[name] += 1
    
    items = d.items()
    items.sort(key=lambda x:x[1])
    for key, value in items:
        print key, value
    

    测试程序完成后,我创建了一个dict并在gc.get_objects()中对对象进行计数。这是输出:
    ...
    wrapper_descriptor 1382
    function 2330
    tuple 9117
    BagObj 10000
    NpzFile 10000
    list 20288
    dict 21001
    

    从结果我们知道BagObj和NpzFile出了点问题。查找代码:
    class NpzFile(object):
        def __init__(self, fid, own_fid=False):
            ...
            self.zip = _zip
            self.f = BagObj(self)
            if own_fid:
                self.fid = fid
            else:
                self.fid = None
    
        def close(self):
            """
            Close the file.
    
            """
            if self.zip is not None:
                self.zip.close()
                self.zip = None
            if self.fid is not None:
                self.fid.close()
                self.fid = None
    
        def __del__(self):
            self.close()
    
    class BagObj(object):
        def __init__(self, obj):
            self._obj = obj
        def __getattribute__(self, key):
            try:
                return object.__getattribute__(self, '_obj')[key]
            except KeyError:
                raise AttributeError, key
    

    NpzFile具有 del (),NpzFile.f是BagObj,而BagObj._obj是NpzFile,这是一个引用周期,将导致NpzFile和BagObj都无法收集。这是Python文档中的一些解释:http://docs.python.org/library/gc.html#gc.garbage

    因此,要打破引用周期,将需要调用“del data.f”

    关于python - 在循环中使用numpy加载时发生内存溢出,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9244397/

    10-09 06:40