R内存管理-增加内存消耗

7

我的代码如下所示(与原始版本相比略有简化,但仍反映了问题)。

require(VGAM)

Median.sum  = vector(mode="numeric", length=75) 
AA.sum      = vector(mode="numeric", length=75)                                                    
BB.sum      = vector(mode="numeric", length=75)                   
Median      = array(0, dim=c(75 ,3)) 
AA          = array(0, dim=c(75 ,3))                                                    
BB          = array(0, dim=c(75 ,3))                              

y.sum     = vector(mode="numeric", length=100000)
y         = array(0, dim=c(100000,3))
b.size    = vector(mode="numeric", length=3) 
c.size    = vector(mode="numeric", length=3) 


for (h in 1:40)
{
  for (j in 1:75)
  {  
    for (i in 1:100000)
    {
      y.sum[i] = 0

      for (f in 1:3)
      {
        b.size[f] = rbinom(1, 30, 0.9)
        c.size[f] = 30 - rbinom(1, 30, 0.9) + 1
        y[i, f] = sum( rlnorm(b.size[f], 8.5, 1.9) ) + 
          sum( rgpd(c.size[f], 120000, 1870000, 0.158) )
        y.sum[i] = y.sum[i] + y[i, f]
      }
    }

    Median.sum[j] = median(y.sum)
    AA.sum[j] = mean(y.sum)
    BB.sum[j] = quantile(y.sum, probs=0.85)

    for (f in 1:3)
    {
      Median[j,f] = median(y[,f])
      AA[j,f] = mean(y[,f])
      BB[j,f] = quantile(y[,f], probs=0.85)
    }
  }
  #gc()
}

它在执行过程中中断(h=7,j=1,i=93065),并显示错误:

Error: cannot allocate vector of size 526.2 Mb

刚刚收到这条信息后,我阅读了这个这个这个,但仍然不够。问题是,无论是垃圾回收器(gc()),还是清除工作区中的所有对象都没有帮助。我的意思是我已经尝试在代码中同时使用垃圾回收器和操作,在循环内删除所有变量并重新声明它们(请注意# gc()所在的位置,但后者未包含在我发布的代码中)。
对于我来说,这似乎很奇怪,因为整个过程在每个循环步骤中使用相同的对象(=>应该在每个循环步骤中消耗相同的内存)。为什么内存消耗随时间增加呢?
更糟糕的是,如果我想在同一个R会话中工作,甚至执行:
rm(list=ls())
gc()

即使我想声明一些微小的东西,例如:

,我仍然会收到相同的错误消息。

abc = array(0, dim=c(10,3))

只有关闭R并开始新会话才能解决问题,为什么?也许有一些方法可以重新编写我的循环?
R版本:2.15.1(32位),操作系统:Windows XP(32位)
我在这里比较新,因此非常感谢每一个提示!提前致谢。
编辑:(来自Arun)。我发现即使只有一个简单的例子,也可以更容易地重现这种行为。启动一个新的R会话,将此代码复制并粘贴,观察系统监视器中的内存增长。
mm <- rep(0, 1e4) # initialise a vector
for (i in 1:1e3) {
    for (j in 1:1e3) {
        for (k in 1:1e4) {
            mm[k] <- k # already pre-allocated
         }
    }
}

@ Roman:rgpd从广义帕累托分布中绘制随机值。y.sum真的在增长吗?它在代码的最开始就被声明了。 - brunner
使用 for (i in 1:1000)(包括所有虚拟值)需要870MB... - Arun
1
@brunner 非常直白地说,<quote>"32位和64位这两个术语是指计算机处理器(也称为CPU)处理信息的方式。Windows的64位版本比32位系统更有效地处理大量的随机访问内存(RAM)"<unquote> - Arun
一般来说,64位系统的内存分配和处理比32位更好。我的意思是,你会比使用64位系统的人更快遇到“内存不足”的问题。 - Arun
1
我可以通过@Arun提供的示例重现问题。我正在使用RStudio上的Linux操作系统,版本为R 2.15.3 64位。可以观察到进程“rstudio”的逐步内存跳跃:170M、194M、224M、259M、301M、347M、408M等。 - djhurio
显示剩余19条评论
2个回答

4
for (i in 1:100000) 循环内添加对 gc() 的调用。
在 Arun 的代码紧密循环中添加对 gc() 的调用可以消除其内存增长。
这展示了内存增长:
mm <- rep(0, 1e4) # initialise a vector
for (i in 1:1e3) {
    for (j in 1:1e3) {
        for (k in 1:1e4) {
            mm[k] <- k # already pre-allocated
         }
     }
 }

这不符合要求:
mm <- rep(0, 1e4) # initialise a vector
for (i in 1:1e3) {
    for (j in 1:1e3) {
        for (k in 1:1e4) {
            mm[k] <- k # already pre-allocated
            gc()
         }
     }
 }

这里自动垃圾回收有些问题。在第一种情况下,调用了收集器,如gcinfo(TRUE)所示。但是内存却非常快地增长。


我只是在测试同样的东西,这似乎可以工作,但它并没有回答为什么自动垃圾回收在这里不起作用的问题。此外,如果您首先在没有 gc() 的情况下运行代码一段时间,然后再运行第二个代码,它仍然不会删除早期代码中保留的内存。 - Jouni Helske
@ Matthew:谢谢,我会尝试在“非常中间”的循环中放置gc()。我会告诉你结果的。但是 - Hemmo是正确的。 - brunner
它在Arun的代码中也不应该有任何影响,但实际上确实有。 - Matthew Lundberg
@ Matthew:可能你是对的,但是在“非常中间”的循环中放置gc()之后,该过程太耗费时间,以至于完全没有用处。 - brunner

2
这种方式似乎可行(将最内层循环放入函数中)。我没有运行到最后,因为速度太慢了,但是我没有注意到像你代码中那样的内存膨胀。
require(VGAM)

Median.sum  = vector(mode="numeric", length=75) 
AA.sum      = vector(mode="numeric", length=75)                                                    
BB.sum      = vector(mode="numeric", length=75)                   
Median      = array(0, dim=c(75 ,3)) 
AA          = array(0, dim=c(75 ,3))                                                    
BB          = array(0, dim=c(75 ,3))                              


inner.fun <- function() {
  y.sum     = vector(mode="numeric", length=100000)
  y         = array(0, dim=c(100000,3))
  b.size    = vector(mode="numeric", length=3) 
  c.size    = vector(mode="numeric", length=3) 
  for (i in 1:100000)
    {
      y.sum[i] = 0

      for (f in 1:3)
      {
        b.size[f] = rbinom(1, 30, 0.9)
        c.size[f] = 30 - rbinom(1, 30, 0.9) + 1
        y[i, f] = sum( rlnorm(b.size[f], 8.5, 1.9) ) + 
          sum( rgpd(c.size[f], 120000, 1870000, 0.158) )
        y.sum[i] = y.sum[i] + y[i, f]
      }
    }
    list(y.sum, y)
}

for (h in 1:40)
{
  cat("\nh =", h,"; j = ")
  for (j in 1:75)
  {  
    cat(j," ")
    result = inner.fun()
    y.sum = result[[1]]
    y = result[[2]]
    Median.sum[j] = median(y.sum)
    AA.sum[j] = mean(y.sum)
    BB.sum[j] = quantile(y.sum, probs=0.85)

    for (f in 1:3)
    {
      Median[j,f] = median(y[,f])
      AA[j,f] = mean(y[,f])
      BB[j,f] = quantile(y[,f], probs=0.85)
    }
  }
}

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