使用rpy时出现内存泄漏问题

5

我在代码中有一个类似于这个的小部分(当然,实际上使用的是真实矩阵而不是填充了零的矩阵):

x = [rinterface.FloatSexpVector([0]*(1000**2)) for i in xrange(20)]
y = robjects.r('list')(x)

看起来这可能会导致内存泄漏。

运行以下代码时:

for i in xrange(10):
    x = [rinterface.FloatSexpVector([0]*(1000**2)) for i in xrange(20)]
    y = robjects.r('list')(x)
    del x
    del y
    robjects.r('gc(verbose=TRUE)')

I get:

Error: cannot allocate vector of size 7.6 Mb
In addition: Warning messages:
1: Reached total allocation of 2047Mb: see help(memory.size)
2: Reached total allocation of 2047Mb: see help(memory.size)
3: Reached total allocation of 2047Mb: see help(memory.size)
4: Reached total allocation of 2047Mb: see help(memory.size)

这是一个bug还是我需要进行其他操作?我也尝试过将变量命名为robjects.globalenv中的名称,然后在执行gc()之前对其进行rm()处理,但似乎不起作用。
我应该提一下,我正在windows上运行rpy 2.3dev,但在linux上也会出现这种情况,使用的是rpy 2.2.6(尽管由于linux运行64位版本而不是像windows机器一样运行32位版本,内存仅增长而不会出现2047mb错误)。
编辑: 在第一个代码示例之前添加gc.collect()似乎解决了问题,但这没有解决我的问题-深入研究我的代码后,我发现导致问题的那一行是赋值到.names,类似于这样:
x = [rinterface.FloatSexpVector([0]*(1000**2)) for i in xrange(20)]
y = robjects.r('list')(x)[0]
y.names = rinterface.StrSexpVector(['a']*len(y))

在清理之前放置rinterface.NULL也没有帮助。有什么建议吗?

回答时我忘了提到Windows这一部分。有两点需要注意:1)Windows并不是真正支持的(所以现在让我们坚持使用Linux),2)如果你使用Windows,那么我会想知道为什么我们没有收到你在Windows上为rpy2做出的贡献。 - lgautier
嗯,基本上目前的Windows版本已经足够好了。我其实已经开始着手处理它了,但是后来发现有人已经发布了新版本,而且对我来说它很好用...也许当我遇到下一个Windows特定的问题时,我会再次处理它。 - itai
2个回答

2
可能是因为Python不知道嵌入式R分配的内存量,因此不知道应该收集垃圾。
关于内存使用情况,文档中有一些内容,请参见rpy2的文档,以及在Stack Overflow上的早期问题
您的编辑表明可能有一些问题。最好在rpy2的bitbucket页面上提交错误报告,并继续在那里进行故障排除,而不是在这里。

谢谢,那很有帮助。但我进一步调查了问题 - 我发现还有另一个问题..请看我的编辑.. - itai

0

我不认为这是内存泄漏。我会尝试给你以下的视角:

在Python shell中尝试这些示例:

l = range(32 * 1024 * 1024)

因此,我们尝试让解释器分配128 MB的连续内存区域。这将起作用(在我的机器上需要约7秒)

您可以尝试使用各种值(256MB仍然有效);还可以尝试N = 128 * 1024 * 1024;从这个值开始,我的机器就会卡住。如果我足够耐心,几分钟后可能会恢复。但问题是,解释器不能轻松地分配大块的连续内存区域。

值得一提的是,我可以以同样的方式在C++中分配1GB的内存,在同一台机器上只需要不到1秒钟的时间(i7,8GB RAM,Windows 8或CentOS6 - 我尝试了两个操作系统)。我也尝试了Java。

我没有花时间去研究为什么Python堆分配器会表现出这种行为。我只能推测rpy的人们试图阻止/限制您分配过多的内存,因此他们设置了一个下限,以确保不会发生任何不良情况;实际上,您可以有多个较小的数组,并在其中放置一些引用对象(占用超过4个字节)。


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