在IPython中释放巨大numpy数组的内存

60

更新:在重启机器后,这个问题自己解决了。目前还不能确定为什么之前会出现这个错误。

我有一个函数,加载一个很大的numpy数组(约980MB)并返回它。

当我第一次启动Ipython并调用这个函数时,它可以将数组加载到变量中而不会出现任何问题。

但是如果我再次运行相同的命令,它会引发“内存错误”的错误。

我尝试了以下方法:

del hugeArray

仍然发生了相同的错误。 我甚至尝试了以下内容

del hugeArray
gc.collect()
gc.collect()

最初,gc.collect()返回了145,第二次调用返回了48。 但即使这样,当我调用函数时,仍然会引发内存错误。

唯一的解决方法是重新启动ipython。 有什么办法可以释放ipython中的所有内存,这样我就不必重新启动它了吗?

----------------更新

以下是%whos的输出。

Variable   Type      Data/Info
------------------------------
gc         module    <module 'gc' (built-in)>
gr         module    <module 'Generate4mRamp' <...>rom 'Generate4mRamp.pyc'>
np         module    <module 'numpy' from '/us<...>ages/numpy/__init__.pyc'>
plt        module    <module 'matplotlib.pyplo<...>s/matplotlib/pyplot.pyc'>

其中,gr是我使用的用于加载数据立方体的函数所在的模块。

---------如何重现错误

下面这个简单的函数能够重现该错误。

import numpy as np
import gc

def functionH():
    cube=np.zeros((200,1024,1024))
    return cube

testcube=functionH()   #Runs without any issue 

del testcube
testcube=functionH()  # Raises Memory Error

del testcube
gc.collect()
gc.collect()
testcube=functionH()  # Still Raises Memory Error

这个错误只在Ipython中出现,在简单的Python( >>> )中执行 del testcube 后,并不会出现内存错误。


1
你可以尝试在IPython中调用whos命令来查找占用内存的内容吗? - tiago
@tiago:我已经添加了%whos命令的输出。它只显示我加载的模块,没有其他东西。 - indiajoe
sys.getrefcount(testcube) 的输出结果是 2。 - indiajoe
嘿,突然间它开始工作了。在执行了删除命令后,它能够再次运行函数而不出现内存错误。我将尝试查看中间发生了什么变化。 - indiajoe
这非常奇怪,现在一切都正常工作了。我已经重新启动了机器,并启动了一个纯Python接口,除此之外其他所有内容都是相同的。现在我无法再复制我在问题中提到的任何错误... - indiajoe
显示剩余3条评论
1个回答

62

您是否想查看值?IPython将输出变量缓存为例如Out[8],因此如果检查它,它将保留在内存中。

您可以执行%xdel testcube来删除变量并将其从IPython缓存中删除。或者,%reset out%reset array将清除所有输出历史记录,或仅清除对numpy数组的引用。


我没有在IPython中查看该值。但感谢您提供关于IPython缓存输出的信息。我不知道这一点。下次发生此错误时,我将尝试使用xdel命令。现在,一切都正常。 - indiajoe
4
这是否存在无法正常工作的原因?我尝试执行类似list([i**2 for i in range(30000000)])的操作来测试,然后我尝试执行 %reset out 命令。执行该命令后,Out为空,但内存使用量与重置命令之前相同,可能是什么原因呢?这就像只删除了引用,而没有释放内存? - Kobe-Wan Kenobi
1
我应该补充说明,不带 out%reset 命令可以完成工作。它既清空了内存,又删除了引用。但是我不想失去自己的变量。此外,这个命令也可以实现:v = Out[18] %xdel v。为什么呢? - Kobe-Wan Kenobi
2
%xdel 尝试在 IPython 的机制中查找并删除所有指向对象的引用。 - Thomas K

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接