【问题标题】:Measure peak memory usage in R测量 R 中的峰值内存使用量
【发布时间】:2021-09-30 02:22:10
【问题描述】:

我想在 RStudio 中监控我的内存使用情况,以避免在集群上出现 out-of-memory 错误。我正在寻找一种计算峰值内存使用量的方法,该方法包括全局变量和局部变量。例如,峰值内存使用量应考虑函数和应用循环中的中间变量。

gc(reset = T)
sum(gc()[, "(Mb)"]) # 172Mb

lapply(1:3, function(x) {
  mx <- replicate(10, rnorm(1e6)) # 80Mb object
  mean(mx)
})

sum(gc()[, "(Mb)"]) # 172Mb -- still the same!

【问题讨论】:

  • 你在哪个平台上?您可以使用一堆工具监控 Linux 上的内存使用情况
  • 我在 Mac 上使用 RStudio
  • 最终的方法是为此使用操作系统工具。在 R C 中,您可以使用 R_alloc 或 malloc,后者不会被 R 跟踪。
  • @jangorecki 这可能就是我要找的东西,我会做一些研究

标签: r


【解决方案1】:

lapply 返回的对象仅重 488 字节,因为它被总结为:垃圾回收已删除平均计算后的中间对象。
help('Memory') 提供了有关 R 如何管理内存的有用信息。
特别是,您可以使用object.size() 来跟踪单个对象的大小,并使用memory.size() 来了解每个步骤使用了多少内存:

# With mean calculation
gc(reset = T)
#>          used (Mb) gc trigger (Mb) max used (Mb)
#> Ncells 405777 21.7     831300 44.4   405777 21.7
#> Vcells 730597  5.6    8388608 64.0   730597  5.6
sum(gc()[, "(Mb)"]) 
#> [1] 27.3

l<-lapply(1:3, function(x) {
  mx <- replicate(10, rnorm(1e6)) # 80Mb object
  mean(mx)
  print(paste('Memory used:',memory.size()))
})
#> [1] "Memory used: 271.04"
#> [1] "Memory used: 272.26"
#> [1] "Memory used: 272.26"

object.size(l)
#> 488 bytes


## Without mean calculation :
gc(reset = T)
#>          used (Mb) gc trigger  (Mb) max used (Mb)
#> Ncells 464759 24.9     831300  44.4   464759 24.9
#> Vcells 864034  6.6   29994700 228.9   864034  6.6
gcinfo(T)
#> [1] FALSE
sum(gc()[, "(Mb)"]) 
#> [1] 31.5
l<-lapply(1:4, function(x) {
  mx <- replicate(10, rnorm(1e6))
  print(paste('New object size:',object.size(mx)))
  print(paste('Memory used:',memory.size()))
  mx
})
#> [1] "New object size: 80000216"
#> [1] "Memory used: 272.27"
#> [1] "New object size: 80000216"
#> [1] "Memory used: 348.58"
#> [1] "New object size: 80000216"
#> [1] "Memory used: 424.89"
#> [1] "New object size: 80000216"
#> [1] "Memory used: 501.21"

object.size(l)
#> 320000944 bytes
sum(gc()[, "(Mb)"]) 
#> [1] 336.7

reprex package (v0.3.0) 于 2020 年 8 月 20 日创建

如果不返回mean,而是返回整个对象,那么内存使用量的增加是显着的。

【讨论】:

  • 有没有一种方法可以监控内存使用情况,从而导致垃圾回收?也许是 RStudio 外部的东西?
  • 也许看看help('Memory')。要监督当前内存使用,您可以打印memory.size,查看我的编辑
【解决方案2】:

您可以为此使用gc 函数。

确实,gc 函数 提供了字段 11 和 12 中使用的当前和最大内存(在 Mb 中关于文档,但显然在 Mio 在我的机器上的实践中)。您可以使用参数 reset=TRUE 重置最大值。这是一个例子:

> gc(reset=TRUE)
         used (Mb) gc trigger   (Mb) max used (Mb)
Ncells 318687 17.1     654385   35.0   318687 17.1
Vcells 629952  4.9  397615688 3033.6   629952  4.9
> a = runif(1024*1024*64)  # Should request 512 Mio to the GC (on my machine)
> gc()
           used  (Mb) gc trigger   (Mb) max used  (Mb)
Ncells   318677  17.1     654385   35.0   318834  17.1
Vcells 67738785 516.9  318092551 2426.9 67739236 516.9
> memInfo <- gc()
> memInfo[11]              # Maximum Ncells
[1] 17.1
> memInfo[12]              # Maximum Vcells
[1] 516.9
> rm(a)                    # `a` can be removed by the GC from this point
> gc(reset=TRUE)           # Order to reset the GC infos including the maximum
         used (Mb) gc trigger   (Mb) max used (Mb)
Ncells 318858 17.1     654385   35.0   318858 17.1
Vcells 630322  4.9  162863387 1242.6   630322  4.9
> memInfo <- gc()
> memInfo[11]
[1] 17.1
> memInfo[12]              # The maximum has been correctly reset
[1] 4.9

在本例中,我们可以看到,在围绕runif 调用的两个 gc 调用之间,GC 最多分配了 516.9 - 4.9 = 512 Mb(这与预期结果一致)。

【讨论】:

  • 其实我不认为这个方法考虑了函数和应用循环中的中间值,请看我上面的新测试
  • 是否考虑到不被gc管理的内存?喜欢 malloc 而不是 R_alloc?
  • @jangorecki 不,使用malloc 分配的内存不应被 GC 看到,因为它没有明确要求这样做。但是,AFAIK 大多数 R 库持久对象不是使用普通的malloc 分配的,因为没有收集对象(除非在退出时或由用户手动)。请注意,它可能会在 R 的未来版本中发生变化,因为 4.0 版似乎正在试验引用计数。
【解决方案3】:

我在包裹 peakRAM 中找到了我想要的东西。来自documentation

此软件包可以轻松监控使用的总 RAM 和峰值 RAM,以便开发人员可以快速识别和消除 RAM 饥饿代码。

mem <- peakRAM({
  for(i in 1:5) {
    mean(rnorm(1e7))
  }
})
mem$Peak_RAM_Used_MiB # 10000486MiB

mem <- peakRAM({
  for(i in 1:5) {
    mean(rnorm(1e7))
  }
})
mem$Peak_RAM_Used_MiB # 10005266MiB <-- almost the same!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-02
    • 2016-05-07
    • 2012-03-29
    • 2015-09-17
    • 2017-01-03
    • 1970-01-01
    • 2010-10-20
    相关资源
    最近更新 更多