r - 在R中执行并行计算时,是否有一种释放内存的方法

标签 r memory-management parallel-processing

假设我想使用以下多个内核运行R程序

library(foreach)
library(doParallel)

no_cores <- detectCores() - 2

cl<-makeCluster(no_cores, outfile = "debug.txt")

registerDoParallel(cl)

result <- foreach(i = 10:100, 
        .combine = list,
        .multicombine = TRUE)  %dopar%  {

          set.seed(i)

          a <- replicate(i, rnorm(20)) 
          b <- replicate(i, rnorm(20))

          list(x = a + b, y = a - b)

        } 

但是,我发现程序运行一段时间后,内存使用量增加了。我认为程序不会释放旧对象。所以我尝试使用gc()作为
result <- foreach(i = 10:100, 
        .combine = list,
        .multicombine = TRUE)  %dopar%  {

          set.seed(i)

          a <- replicate(i, rnorm(20)) 
          b <- replicate(i, rnorm(20))

          list(x = a + b, y = a - b)
         gc()

        } 

看来可行,但我没有得到想要的结果。然后我尝试在每个循环之前收集垃圾,但似乎不起作用。
result <- foreach(i = 10:100, 
        .combine = list,
        .multicombine = TRUE)  %dopar%  {
          gc()
          set.seed(i)

          a <- replicate(i, rnorm(20)) 
          b <- replicate(i, rnorm(20))

          list(x = a + b, y = a - b)    
        } 

有办法解决这个问题吗?谢谢大家,任何建议将不胜感激。
PS。这段代码仅供复制,而我真正的仿真程序比这要复杂得多。因此,我不想过多地更改程序结构。

最佳答案

我认为您没有遇到任何所谓的“内存泄漏”,因为对foreach使用更多的迭代只会创建一个更大的数组。如果您的问题是gc()是否真正有用,我建议您阅读Hadley Wickham所著Advanced R的memory usage一章,其中他说:

Despite what you might have read elsewhere, there’s never any need to call gc() yourself


无论如何,我试图找出是您的代码中可能的内存泄漏,将其分为您描述的三个功能或可能性。
library(foreach)
library(doParallel)  
f1 <- function(uu = 10:100){
  no_cores <- detectCores() - 2
  cl<-makeCluster(no_cores)
  registerDoParallel(cl)
  result1 <- foreach(i = uu, .combine = list, 
                     .multicombine = TRUE)  %dopar%  {
                      set.seed(i)
                      a <- replicate(i, rnorm(20)) 
                      b <- replicate(i, rnorm(20))
                      gc()
                      return(list(x = a + b, y = a - b))
                      } 
  stopCluster(cl)
  return(result1)
}
f2 <- function(uu = 10:100){
  no_cores <- detectCores() - 2
  cl<-makeCluster(no_cores)
  registerDoParallel(cl)
  result1 <- foreach(i = uu, .combine = list, 
                     .multicombine = TRUE)  %dopar%  {
                       gc()
                       set.seed(i)
                       a <- replicate(i, rnorm(20)) 
                       b <- replicate(i, rnorm(20))
                       return(list(x = a + b, y = a - b))
                     } 
  stopCluster(cl)
  return(result1)
}
f3 <- function(uu = 10:100){
  no_cores <- detectCores() - 2
  cl<-makeCluster(no_cores)
  registerDoParallel(cl)
  result1 <- foreach(i = uu, .combine = list,  .multicombine = TRUE)  %dopar%  {
                       set.seed(i)
                       a <- replicate(i, rnorm(20)) 
                       b <- replicate(i, rnorm(20))
                       return(list(x = a + b, y = a - b))
                     } 
  stopCluster(cl)
  return(result1)
}

library(pryr)
mem_used() # 214 MB
mem_change(NULL) # 864 B
gc() # whatever
mem_change({res1 <- f1(); rm(res1)}) # 2.11 kB
mem_change({res1 <- f2(); rm(res1)}) # 2.11 kB
mem_change({res1 <- f3(); rm(res1)}) # 2.11 kB
mem_change({res1 <- f1(10:250); rm(res1)}) # 2.11 kB
mem_change({res1 <- f2(10:250); rm(res1)}) # 2.11 kB
mem_change({res1 <- f3(10:250); rm(res1)}) # 2.11 kB
除此之外,我尝试在具有std输入(10:100)的三个函数上运行profvis,并且得到了以下一般时间和内存:
f1():enter image description here f2():enter image description here f3():enter image description here
我不相信profvis结果用于存储时间,但会相信时间。通常,我不会使用gc()释放并行循环中的空间。

关于r - 在R中执行并行计算时,是否有一种释放内存的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43508463/

相关文章:

linux - 分配 "temporary"内存(在 Linux 中)

ios - 为什么在 ARC 中发送消息会导致保留周期警告,但属性集不会?

c++ - Makefile 忽略命令 export OMP_NUM_THREADS

r - 保存 S4 类(class)的最简单方法

r - 在R中使用data.tables的凸包ggplot

r - 使用 R 访问 ACM 数字图书馆 - 没有 API 那么怎么可能?

r - 在 cowplot : How to insert gap between main panel and marginal plots 中使用 axis_canvas 的边缘图

memory-management - 按引用调用和按值返回调用有什么区别

parallel-processing - 对于接受一个函数并返回另一个返回线程句柄的函数的函数,类型签名应该是什么?

parallel-processing - 去函数 channel 中的死锁