64

我在具有64 GB RAM的Windows 64 位计算机上运行模拟。内存使用达到55%,在完成模拟运行后,我删除了工作空间中的所有对象,然后是.rm(list=ls())double gc()

我认为这将为下一次模拟运行释放足够的内存,但实际上内存使用量仅下降了 1%。咨询了很多不同的论坛,我找不到令人满意的解释,只有模糊的评论,例如:

“根据您的操作系统,释放的内存可能不会返回给操作系统,而是保留在进程空间中。”

我想查找以下信息:

  • 1) 哪个操作系统以及在何种条件下释放的内存不会返回给操作系统,以及
  • 2)除了关闭 R 并再次启动它以进行下一次模拟运行之外,是否还有其他补救措施?
4

2 回答 2

41

R垃圾收集器在以下(并非如此)微妙的方面是不完美的:由于它与库交互的方式,它不会移动对象(即,它不会压缩内存)。C(其他一些语言/实现也受此影响,但其他语言/实现尽管也必须与 交互,但设法拥有一个不会受此问题影响压缩分代 GC )。C

这意味着,如果您轮流分配小块内存,然后将其丢弃,而将较大块分配给更永久的对象(这是进行字符串/正则表达式处理时的常见情况),那么您的内存将变得碎片化,垃圾收集器无能为力it:内存已释放,但由于空闲块太短,无法重复使用。

解决此问题的唯一方法是保存所需的对象,重新启动R并重新加载对象。

由于您正在做rm(list=ls()),即您不需要任何对象,因此您不需要保存和重新加载任何内容,因此,在您的情况下,解决方案正是您想要避免的 - 重新启动R

PS1。垃圾收集是一个非常重要的话题。例如,Ruby 在 20 年中使用了 5 种(!)不同的 GC 算法。Java GC 并不糟糕,因为 Sun/ OracleIBM在他们各自的 GC 实现上花费了许多程序员年。另一方面,R 和 Python 的 GC 很糟糕——因为没有人会费心投入必要的人工年数——而且它们很受欢迎。这对你来说更糟就是更好

PS2。相关:R:使用`strsplit`耗尽内存

于 2013-04-21T15:03:45.350 回答
26

你如何检查内存使用情况?通常,虚拟机会分配一些内存块用于存储其数据。一些分配的可能未使用并标记为空闲。GC 所做的是发现未从其他任何地方引用的数据并将相应的内存块标记为未使用,这并不意味着该内存已释放给操作系统。仍然从 VM 的角度来看,现在有更多的可用内存可用于进一步计算。

正如其他人所问的那样,您是否遇到过内存不足的错误?如果没有,那就没什么好担心的了。

编辑: 应该足以理解内存分配和垃圾收集在 R 中是如何工作的。

从第一个文件:

有时会尝试将未使用的页面释放回操作系统。当页面被释放时,等于 R_MaxKeepFrac 乘以为每个类分配的节点数的空闲节点数被保留。发布不需要满足此要求的页面。每个 R_PageReleaseFreq 级别 1 或级别 2 集合都会尝试释放页面。

编辑2:

要查看已用内存,请尝试运行 gc(),并将详细设置为 TRUE:

gc(verbose=T)

这是内存中包含 10'000'000 个整数的数组的结果:

Garbage collection 9 = 1+0+8 (level 2) ... 
10.7 Mbytes of cons cells used (49%)
40.6 Mbytes of vectors used (72%)
          used (Mb) gc trigger (Mb) max used (Mb)
Ncells  198838 10.7     407500 21.8   350000 18.7
Vcells 5311050 40.6    7421749 56.7  5311504 40.6

这是在放弃对它的引用之后:

Garbage collection 10 = 1+0+9 (level 2) ... 
10.7 Mbytes of cons cells used (49%)
2.4 Mbytes of vectors used (5%)
         used (Mb) gc trigger (Mb) max used (Mb)
Ncells 198821 10.7     407500 21.8   350000 18.7
Vcells 310987  2.4    5937399 45.3  5311504 40.6

如您所见,Vcells 使用的内存从 40.6Mb 下降到 2.4Mb。

于 2013-01-29T10:20:12.470 回答