【问题标题】:%dopar% error after several iterations多次迭代后出现 %dopar% 错误
【发布时间】:2016-02-08 16:03:16
【问题描述】:

我一直在尝试在 R 中运行一个并行化的 foreach 循环,它可以正常运行大约十次迭代,但随后崩溃,显示错误:

Error in { : task 7 failed - "missing value where TRUE/FALSE needed"
Calls: %dopar% -> <Anonymous>
Execution halted

我将每个循环的结果附加到一个文件中,该文件确实显示了预期的输出。我的脚本如下,使用this post中的combn_sub函数:

LBRA <- fread(
 input      = "LBRA.012",
 data.table = FALSE)
str_bra <- nrow(LBRA)

br1sums <- colSums(LBRA)
b1non <- which(br1sums == 0)

LBRA_trim <- LBRA[,-b1non]

library(foreach)
library(doMC)
registerDoMC(28)

foreach(X = seq(2, (nrow(LBRA)-1))) %dopar% {
  com <- combn_sub(
   x    = nrow(LBRA),
   m    = X,
   nset = 1000)

  out_in <- matrix(
   ncol = 2,
   nrow = 1)
   colnames(out) <- c("SNPs", "k")

    for (A in seq(1, ncol(com))){
      rowselect <- com[, A]

      sub <- LBRA_trim[rowselect, ]
      subsum <- colSums(sub)

      length <- length(which(subsum != 0)) - 1
      out_in <- rbind(out_in, c(length, X))
    }

  write.table(
   file   = "plateau.csv",
   sep    = "\t",
   x      = out_in,
   append = TRUE)
}

【问题讨论】:

  • 您是否尝试过在不使用%dopar% 的情况下运行前 10 次迭代来查看它在哪一行失败?我的猜测是,该行数据中的某些内容与其他未被考虑的数据行不同。
  • 从并行循环内部写入文件对我来说似乎是不明智的。
  • 在调用 registerDoMC(28) 之前显式创建您的多核集群并指定一个日志文件。这样你就可以看到发生了什么:cluster &lt;- makeCluster(28, outfile="MulticoreLogging.txt"); registerDoMc(cluster);

标签: r domc


【解决方案1】:

我的 foreach 调用也遇到了类似的问题...

tmpcol <- foreach(j = idxs:idxe, .combine=cbind) %dopar% { imp(j) }

Error in { : task 18 failed - "missing value where TRUE/FALSE needed"

更改 .errorhandling 参数只会忽略错误

tmpcol <- foreach(j = idxs:idxe, .combine=cbind, .errorhandling="pass") %dopar% { imp(j) }

Warning message:
In fun(accum, result.18) :
  number of rows of result is not a multiple of vector length (arg 2)

我建议在 foreach 调用中为 X=7 运行该函数。我的问题是我的函数 imp(j) 抛出了一个错误(对于 j=18,它在 NA 计算上遇到问题),导致 foreach 的输出模糊。

【讨论】:

    【解决方案2】:

    正如@Roland 指出的那样,在foreach 循环中写入文件是一个非常糟糕的主意。即使在append 模式下写入,各个内核也会尝试同时写入文件,并且可能会破坏彼此的输入。相反,使用.combine="rbind" 选项捕获foreach 语句的结果,然后在循环后写入文件:

    cluster <- makeCluster(28, outfile="MulticoreLogging.txt");
    registerDoMc(cluster);
    
    foreach_outcome_table <- foreach(X = seq(2, (nrow(LBRA)-1)), .combine="rbind") %dopar% {
    
      print(cat(paste(Sys.info()[['nodename']], Sys.getpid(), sep='-'), "now performing loop", X, "\n"));
    
      com <- combn_sub(x = nrow(LBRA), m = X, nset = 1000);
    
      out_in <- matrix(ncol = 2,nrow = 1);
    
      colnames(out_in) <- c("SNPs", "k");
    
      for (A in seq(1, ncol(com))){
        rowselect <- com[, A];
    
        sub <- LBRA_trim[rowselect, ];
        subsum <- colSums(sub);
    
        length <- length(which(subsum != 0)) - 1;
        out_in <- rbind(out_in, c(length, X));
      }
      out_in;
    }
    write.table(file = "plateau.csv",sep = "\t", x = foreach_outcome_table, append = TRUE);
    

    此外,您可以用nested foreach loop 替换内部的for 循环,这可能会更有效。

    【讨论】:

    • 感谢您的建议。我的初始脚本没有写入循环内的文件,但我添加了它以查看崩溃发生的时间点。
    • 这是有道理的。创建集群时的多核日志记录是减少冲突的更好选择。您甚至可以让各个内核指定它们的 ID,这样您就可以确定哪个内核在做什么。我使用 print(cat(paste(Sys.info()[['nodename']], Sys.getpid(), sep='-'), "now performing action X")); 或类似的东西在 foreach 循环中编写状态更新以进行跟踪。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-13
    • 1970-01-01
    • 2021-06-14
    • 2022-12-18
    • 1970-01-01
    相关资源
    最近更新 更多