我正在使用来自doSMP包的嵌套foreach来基于我开发的功能生成结果。通常,问题将使用三个嵌套循环,但是由于生成的结果的大小(每个i大约为80,000),当最终结果矩阵超过指定的行数时,我不得不暂停编译并将结果写入文件。

i = 1
write.off = 1

while(i <= length(i.vector)){
        results.frame = as.data.frame(matrix(NA, ncol = 3, nrow = 1))

        while(nrow(results.frame) < 500000 & i <= length(i.vector)){
                results = foreach(j = 1:length(j.vector), .combine = "rbind", .inorder = TRUE) %:%
                foreach(k = 1:length(k.vector), .combine = "rbind", .inorder = TRUE) %dopar%{

                        ith.value = i.vector[i]
                        jth.value = j.vector[j]
                        kth.value = k.vector[k]
                        my.function(ith.value, jth.value, kth.value)
                }

                results.frame = rbind(results.frame, results)
                i = i + 1
        }

        results.frame = results.frame[-1,]
        write.table(results.frame, paste("part_",write.off, sep = ""))
        write.off = write.off + 1
}

我遇到的问题是垃圾回收。这些工作人员似乎并没有将内存重新分配给系统,因此在i = 4时,他们每个人都消耗了大约6GB的内存。

我尝试将gc()直接插入到foreach循环以及基础函数中,并且还尝试将函数及其结果分配给我可以定期清除的命名环境。这些方法均无效。

我觉得foreach的initEnvir和finalEnvir参数可能提供了一个解决方案,但是文档和示例并没有对此提供太多帮助。

我在运行Windows Server 2008的VM上运行此代码。

最佳答案

您可以考虑通过编写不同的循环来完全避免此问题。

考虑在gen.factorial中使用AlgDesign函数,例如:

fact1 = gen.factorial(c(length(i.vector), length(j.vector), length(k.vector)), nVars = 3, center = FALSE)
foreach(ix_row = 1:nrow(fact1)) %dopar% {
  my.function(fact1[ix_row,])
}

您还可以使用内存映射文件,并使用bigmemory来预分配输出存储(假设您正在创建矩阵),这将使每个工作人员自己存储输出是可行的。

这样,您的整体内存使用量应该会急剧下降。

更新1:似乎内存问题是doSMP特有的。查看以下帖子:
  • Answer by Revo engineer discusses some memory & process issues
  • Joris Meys reports that doSMP crashes his R instances frequently

  • 我回想起doSMP出现了另一个内存问题,无论是作为问题还是在R聊天中,但我似乎都无法恢复该帖子。

    更新2:我不知道这是否有帮助,但是您可以尝试使用显式的return()(例如return(my.function(ith.value, jth.value, kth.value)))。在我的代码中,为清楚起见,我通常使用显式的return()

    10-07 19:57
    查看更多