为什么save和saveRDS在dopar中的行为不同?

时间:2016-08-08 19:44:46

标签: r foreach machine-learning parallel-processing r-caret

(这是我第一次尝试创建一个可重复的示例问题 - 请随意用更好的方式进行评论来描述或说明问题!)

主要问题声明

我使用foreach' %dopar%caretList(来自caretEnsemble包)并行训练~25,000个模型。由于R崩溃和内存问题,我需要将每个预测保存为单个对象,因此我的工作流程看起来像这样 - 请参阅下面的可重现示例。

cl <- makePSOCKcluster(4)
clusterEvalQ(cl, library(foreach))
registerDoParallel(cl)

multiple.forecasts <- foreach(x=1:1,.combine='rbind',.packages=c('zoo','earth','caret',"glmnet","caretEnsemble")) %dopar% {
  tryCatch({
    results <- caretList(mpg ~ cyl,data=mtcars,trControl=fitControl,methodList=c("glmnet","lm","earth"),continue_on_fail = TRUE)
    for (i in 1:length(results)) {
      results[[i]]$trainingData <- c() ## should be trimming out trainingData
    }
    save(results,file="foreach_results.Rdata") ## export each caretList as its own object
    1
  },
  error = function(e) {
    write.csv(e$message,file="foreach_failure.txt") ## monitor failures as needed
    0
  }
  )
}

(IRL此项目不涉及mtcars数据 - foreach循环的每次迭代都会迭代列表中的一个数据框,并为每个数据框保存一个新的预测对象。)

当此对象保存在foreach循环内时,由于压缩,Windows中的对象大小约为136 KB。

但是,使用foreach创建并保存时,如下所示:

results <- caretList(mpg ~ cyl,data=mtcars,trControl=fitControl,methodList=c("glmnet","lm","earth"),continue_on_fail = TRUE)
for (i in 1:length(results)) {
    results[[i]]$trainingData <- c()
}
save(results,file="no_foreach_results.Rdata")

此对象大致相同,在Windows中约为156KB。那么在Windows中添加到保存的对象大小的是什么?

在实际工作流程中,较小的非foreach对象平均大约为4 MB,较大的foreach对象平均为10 MB,因此当我保存时,这会产生真正的存储问题这些文件大约有25,000个。

  • 为什么在foreach循环中保存的对象大小要大得多,如果可以做些什么呢?

注意

  • 我的假设是save foreach保存了整个环境:而不仅仅是保存对象,即使它被命令使用{ {1}}(见下文),有一些隐含的环境保存导出到每个工人。
  • saveRDS似乎无法在Trim 内工作:caretList trim选项似乎并不适合正在修剪它应该是什么,因为我不得不手动添加命令以修剪trainControl
  • 我目前的解决方法是将trainingData压缩设置为save :我需要使用foreach循环来利用多个核心,因此我需要更大的对象。这会使工作流程减慢大约3-4倍,这就是我寻找解决方案的原因。
  • 需要PSOCK群集来解决xz并行化中的问题:请参阅答案here
  • caret无法解决问题:我已使用SaveRDS代替saveRDS进行了测试,但对象大小的差异普遍存在。< / LI>
  • 删除save对问题没有帮助:即使没有tryCatch循环中的tryCatch,对象大小的差异也会普遍存在。

技术细节

可重复示例:

foreach

sessionInfo()输出:

library(caret)
library(caretEnsemble)

## train a caretList without foreach loop
fitControl <- trainControl(## 10-fold CV
  method = "repeatedcv",
  number = 10,
  ## repeated ten times
  repeats = 10,
  trim=TRUE)

results <- caretList(mpg ~ cyl,data=mtcars,trControl=fitControl,methodList=c("glmnet","lm","earth"),continue_on_fail = TRUE)
for (i in 1:length(results)) {
    results[[i]]$trainingData <- c()
}
object.size(results) ##returns about 546536 bytes
save(results,file="no_foreach_results.Rdata") ##in Windows, this object is about 136 KB

## train a caretList with foreach loop
library(doParallel)

cl <- makePSOCKcluster(4)
clusterEvalQ(cl, library(foreach))
registerDoParallel(cl)

multiple.forecasts <- foreach(x=1:1,.combine='rbind',.packages=c('zoo','earth','caret',"glmnet","caretEnsemble")) %dopar% {
  tryCatch({
    results <- caretList(mpg ~ cyl,data=mtcars,trControl=fitControl,methodList=c("glmnet","lm","earth"),continue_on_fail = TRUE)
    for (i in 1:length(results)) {
      results[[i]]$trainingData <- c()
    }
    save(results,file="foreach_results.Rdata") ## in Windows, this object is about 160 KB
    ## loading this file back in and running object.size gives about 546504 bytes, approximately the same
    1
  },
  error = function(e) {
    write.csv(e$message,file="foreach_failure.txt")
    0
  }
  )
}

1 个答案:

答案 0 :(得分:0)

我也不知道为什么,但我提出的解决方法就是运行

RM(train_data)

从环境中删除任何重型存储 - 例如训练数据集 - 并阻止它被保存到磁盘。

(很高兴,这不是我疯狂的事情。)