【问题标题】:Delete global variable and release memory from a function从函数中删除全局变量并释放内存
【发布时间】:2019-05-29 13:37:08
【问题描述】:

我需要删除一个全局变量并从 R 函数内部释放它正在使用的内存,但我尝试过的所有选项都不起作用。

我已经尝试了带有envir参数的rm函数,然后是gc,但是gc并没有释放内存。我还尝试使用 eval+envir 在全局环境中运行 gc。

library(data.table)
DT = data.table(col1 = 1:1e6)
cols = paste0('col', 2:100)
for (col in cols){ DT[, col := 1:1e6, with = F] }

rm_and_release <- function(dt){
  dt <- dt[sample(1e6, 9e5, FALSE)]
  print(gc())
  rm(DT, envir = globalenv())

  print(gc())
}

rm_and_release(DT)

结果如下

           used  (Mb) gc trigger   (Mb)  max used   (Mb)
Ncells   661556  35.4    1168576   62.5   1143443   61.1
Vcells 96303112  734.8   146725516 1119.5 146722586 1119.5
           used  (Mb) gc trigger   (Mb)  max used   (Mb)
Ncells   661569  35.4    1168576   62.5   1143443   61.1
Vcells 96303114  734.8   146725516 1119.5 146722586 1119.5

我预计第二个 gc() 会释放更多内存,因为此时只有一个数据集,因为全局 DT 已被删除。

我需要释放函数内部的 RAM,因为该函数会生成更多数据集并且内存不足。

【问题讨论】:

    标签: r memory


    【解决方案1】:

    像这样使用rmlist= 参数:

    library(data.table)
    DT = data.table(col1 = 1:1e6)
    cols = paste0('col', 2:100)
    for (col in cols){ DT[, col := 1:1e6, with = F] }
    
    rm_and_release <- function(dt){
      dt <- dt[sample(1e6, 9e5, FALSE)]
      print(gc())
      rm(list = "DT", envir = globalenv())
    
      print(gc())
    }
    
    rm_and_release(DT)
    exists("DT")
    ## [1] FALSE
    

    注意

    这是我运行它时的日志(在 Windows 上):

    > library(data.table)
    > gc()
              used (Mb) gc trigger  (Mb) max used  (Mb)
    Ncells 1075660 57.5    1899034 101.5  1899034 101.5
    Vcells 2609137 20.0   91310117 696.7 99059673 755.8
    > DT = data.table(col1 = 1:1e6)
    > cols = paste0('col', 2:100)
    > for (col in cols){ DT[, col := 1:1e6, with = F] }
    There were 50 or more warnings (use warnings() to see the first 50)
    > 
    > rm_and_release <- function(dt){
    +   dt <- dt[sample(1e6, 9e5, FALSE)]
    +   print(gc())
    +   rm(list = "DT", envir = globalenv())
    + 
    +   print(gc())
    + }
    > 
    > gc()
               used  (Mb) gc trigger  (Mb) max used  (Mb)
    Ncells  1076769  57.6    1899034 101.5  1899034 101.5
    Vcells 53024698 404.6   91310117 696.7 99059673 755.8
    > rm_and_release(DT)
               used  (Mb) gc trigger   (Mb) max used  (Mb)
    Ncells  1075902  57.5    1899034  101.5  1899034 101.5
    Vcells 97613454 744.8  134081733 1023.0 99059673 755.8
               used  (Mb) gc trigger   (Mb) max used  (Mb)
    Ncells  1075901  57.5    1899034  101.5  1899034 101.5
    Vcells 97613454 744.8  160978079 1228.2 99059673 755.8
    > exists("DT")
    [1] FALSE
    > gc()
              used (Mb) gc trigger  (Mb) max used  (Mb)
    Ncells 1075669 57.5    1899034 101.5  1899034 101.5
    Vcells 2613271 20.0  128782463 982.6 99059673 755.8
    > ## [1] FALSE
    

    【讨论】:

    • 当然这也很糟糕,无论函数的输入是什么,都删除一个名为 DT 的对象。
    • 发帖人没有描述他的意图,但只给出了代码,并且该代码试图删除 DT 而不管 dt 所以我只是修复它以实际删除它,同时保留似乎是初衷。如果这不是他的意图,那么问题需要解决。
    • 我试过你的代码,但我发现对象被删除但内存没有释放,两个 gc() 都显示正在使用的内存在 730 mb 左右。在第二个 gc() 中,我们少了一个 data.table,因此使用的内存应该更少。谢谢。
    • 日志显示在最后的注释中。 Ncells 和 Vcells 没有改变,表明任何中间内存分配已释放。
    • 谢谢@G.Grothendieck。但是,直到函数结束才释放内存,我需要先释放它,因为我真正的函数在最后使用了更多的内存并且用完了它。我不确定我的意图是否明确。我已经发布了一个答案(不太漂亮),其中内存在函数内部释放。
    【解决方案2】:

    我找到了一些有效的代码

    library(data.table)
    DT = data.table(col1 = 1:1e6)
    cols = paste0('col', 2:100)
    for (col in cols){ DT[, col := 1:1e6, with = F] }
    
    rm_and_release <- function(){
      dt <- copy(DT)
      dt <- dt[sample(1e6, 9e5, FALSE)]
      print(gc())
      rm(DT, envir = globalenv())
    
      print(gc())
    }
    
    rm_and_release()
    

    结果

               used  (Mb) gc trigger   (Mb)  max used   (Mb)
    Ncells   865272  46.3    1442291   77.1   1280599   68.4
    Vcells 96733883 738.1  167167064 1275.4 147681076 1126.8
               used  (Mb) gc trigger   (Mb)  max used   (Mb)
    Ncells   865173  46.3    1442291   77.1   1280599   68.4
    Vcells 46731629 356.6  133733651 1020.4 147681076 1126.8
    

    我认为不插入 DT 作为函数的参数非常难看,但至少在这种情况下内存从 738Mb 降低到 356Mb,这对我正在做的事情至关重要

    【讨论】:

      猜你喜欢
      • 2021-05-29
      • 2018-05-22
      • 1970-01-01
      • 2013-01-03
      • 2011-02-10
      • 2017-05-18
      • 2015-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多