【问题标题】:Unexpected R memory management behaviour意外的 R 内存管理行为
【发布时间】:2018-08-04 11:31:06
【问题描述】:

过去几天我一直在寻找我认为是我编写的 R 程序某处的内存泄漏。事实证明,这是由我不太了解的一些 R 特性引起的。我的预感是它与承诺和惰性评估有关。以下是重现问题的示例:

M <- matrix(rnorm(1E7), 1000)
format(object.size(M), "Mb") ## An 80 Mbs matrix
gc() ## Memory usage should be around 80 Mbs
LF <- apply(M, 1, function(X) {sdX <- sd(X); function(X) X / sdX})
format(object.size(LF), "Mb") ## 2.9 Mb (isn't it a lot for a few functions? but it's not really the point)
gc() ## Memory usage is at 158 Mbs event though our workspace only contains two objects of 80 and 2.9 Mbs
rm(M)
gc() ## Back to around 80 Mbs but M is gone
rm(LF)
gc() ## Back to normal

您可以看到,如果我们过于频繁地重复该操作,那么内存使用量就会变得失控。 似乎 R 需要存储整个矩阵才能调用LF 中的函数。关于我们在LF 中创建函数时会发生什么的任何见解?解决方法?

【问题讨论】:

  • 您正在那里创建闭包。查看ls(envir = environment(LF[[1]]))。 R 必须将这些对象与每个函数相关联,否则如果您从全局环境中删除 M,它们将无法工作。我的建议:不要这样做。如果您描述了这样做的原因,我们可以提出替代方案。
  • 目标是创建转换一组变量的函数。在示例中,矩阵的每一列都是不同的变量。请注意,这是我在程序中所做的简化版本。我知道 R 必须在某处保存 sdX 但为什么它会存储整个列?它可以只存储很小的sdX 的值

标签: r memory memory-management memory-leaks promise


【解决方案1】:

你返回的函数的封闭环境是传递给apply的函数的本地环境。显然,函数参数必须存储在这个环境中。通常这个环境在调用之后会丢失,但是你会保留它,因为你返回了一个闭包。您可以删除不需要的对象:

LF <- apply(M, 1, function(X) {sdX <- sd(X); rm("X"); function(X) X / sdX})
ls(envir = environment(LF[[1]]))
#[1] "sdX"

但是,我仍然看不出使用闭包的理由,并建议重新设计您的整个方法。例如,在这个特定示例中,我将返回标准偏差并将它们作为参数传递给转换函数。

【讨论】:

    猜你喜欢
    • 2020-05-01
    • 2015-04-26
    • 2013-01-31
    • 2011-01-05
    • 2017-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-28
    相关资源
    最近更新 更多