覆盖R对象时如何管理内存?

时间:2015-04-30 11:01:59

标签: r performance memory bigdata

我正在处理一些大型数据集,并且正在尽我所能保持R的内存限制。关于覆盖R对象的一个​​问题。我有一个大的data.table(或任何R对象),它必须多次复制到tmp。问题是:如果我在覆盖之前删除tmp会有什么不同吗?在代码中:

for (1:lots_of_times) {
     v_l_d_t_tmp <- copy(very_large_data_table) # Necessary copy of 7GB data
                                                # table on 16GB machine. I can
                                                # afford 2 but not 3 copies.
     ### do stuff to v_l_d_t_tmp and output
     rm (v_l_d_t_tmp)  # The question is whether this rm keeps max memory
                        # usage lower, or if it is equivalent to what an 
                        # overwrite will automatically do on the next iteration.
}

假设副本是必要的(如果我在每个循环中达到需要从磁盘读取very_large_data_table的点,我会这样做,但问题是:它会对最大内存使用量产生任何影响吗?如果我再次加载之前明确删除v_l_d_t_tmp?)。

或者,为了教导男人钓鱼,我可以输入什么(在R中,让我们不进入ps)来回答这个问题?

如果答案结果是:“信任垃圾收集。”

2 个答案:

答案 0 :(得分:2)

这是另一个想法......它没有直接回答你的问题,而是试图通过另一种方式消除内存问题来绕过它。可能会让你思考:

如果您改为缓存very_large_data_table,然后只读一次,执行您需要做的操作,然后退出R.现在,在R 之外写一个循环,然后记忆问题消失了。当然,这会花费你更多的CPU,因为你必须多次读取7GB ......但是可能值得节省内存成本。实际上,这会减少你的内存使用,因为你不必复制表。

另外,就像@konvas在评论中指出的那样,我也发现rm()即使gc()也没有得到我需要的长循环,内存会累积并最终陷入困境。退出R是一个简单的出路。

我经常这样做,所以我写了一个包来帮助我缓存这样的对象:simpleCache

如果你有兴趣尝试,它看起来像这样:

在R之外做这件事:

for (1:lots_of_times) {
Rscript my_script.R
}

然后在R中,执行此操作... my_script.R:

library(simpleCache)
simpleCache("very_large_data_table", {r code for how 
you make this table }, assignTo="v_l_d_t_tmp") 

 ### do stuff to v_l_d_t_tmp and output

答案 1 :(得分:1)

这是一个评论而不是一个答案,但它变得太长了。

我想在这种情况下,对rm的调用可能是正确的。我认为从第二次迭代开始,如果你不打电话rm,你可能在内存中有3个表。在复制大对象时,R无法在复制结束之前释放v_l_d_t_tmp占用的内存,因为函数调用可能有错误,在这种情况下必须保留旧对象。考虑这个例子:

 x<-1:10
 myfunc<-function(y) {Sys.sleep(3);30}

这里我定义了一个对象和一个需要一些时间来做某事的函数。如果您尝试:

 x<-myfunc()

并在结束之前中断执行&#34;当然&#34;,对象x仍然存在,其1:10内容。因此,我想在您的情况下,即使您使用相同的符号,R也无法在复制之前或期间释放其内容。如果您在以下副本之前删除它,它可以。当然,复制后将删除该对象,但在此期间可能会耗尽内存。

我绝不是R内幕的专家,所以不要理所当然地说我刚刚说的话。