保存foreach dopar loop的多个输出

May*_*you 24 parallel-processing foreach r

我想知道是否/如何作为foreach dopar循环的一部分返回多个输出.

我们来看一个非常简单的例子.假设我想将2个操作作为foreach循环的一部分,并且希望为每个值返回或保存两个操作的结果i.

对于只返回一个输出,它将如下所示:

library(foreach)
library(doParallel)
cl <- makeCluster(3)
registerDoParallel(cl)

oper1 <- foreach(i=1:100000) %dopar% {
    i+2
}
Run Code Online (Sandbox Code Playgroud)

oper1将是一个包含100000个元素的列表,每个元素都是i+2i的每个值的操作结果.

假设现在我想分别返回或保存两个不同操作的结果,例如i+2i+3.我尝试了以下方法:

oper1 = list()
oper2 <- foreach(i=1:100000) %dopar% {
    oper1[[i]] = i+2
    return(i+3)
}
Run Code Online (Sandbox Code Playgroud)

希望结果i+2将保存在列表中oper1,并且i+3将返回第二个操作的结果foreach.但是,列表中没有任何内容oper1!在这种情况下,只有i+3从循环返回的结果.

有没有办法在两个单独的列表中返回或保存两个输出?

Ste*_*ton 36

不要尝试使用foreach或任何其他并行程序包的副作用.而是返回列表中foreach循环体的所有值.如果您希望最终结果是两个列表的列表而不是100,000个列表的列表,那么请指定一个转换结果的组合函数:

comb <- function(x, ...) {
  lapply(seq_along(x),
    function(i) c(x[[i]], lapply(list(...), function(y) y[[i]])))
}

oper <- foreach(i=1:10, .combine='comb', .multicombine=TRUE,
                .init=list(list(), list())) %dopar% {
  list(i+2, i+3)
}

oper1 <- oper[[1]]
oper2 <- oper[[2]]
Run Code Online (Sandbox Code Playgroud)

请注意,此组合函数需要使用.init参数来设置x第一次调用combine函数的值.

  • 答案并没有解释它在数据,帧,矩阵或向量的场景中如何发挥作用 (3认同)

Con*_*ngo 6

我更喜欢使用一个类来保存%dopar%循环的多个结果。

本示例启动3个核,在每个核上计算多个结果,然后将结果列表返回给调用线程。

下测试RStudioWindows 10R v3.3.2

library(foreach)
library(doParallel)

# Create class which holds multiple results for each loop iteration.
# Each loop iteration populates two properties: $result1 and $result2.
# For a great tutorial on S3 classes, see: 
# http://www.cyclismo.org/tutorial/R/s3Classes.html#creating-an-s3-class
multiResultClass <- function(result1=NULL,result2=NULL)
{
  me <- list(
    result1 = result1,
    result2 = result2
  )

  ## Set the name for the class
  class(me) <- append(class(me),"multiResultClass")
  return(me)
}

cl <- makeCluster(3)
registerDoParallel(cl)
oper <- foreach(i=1:10) %dopar% {
   result <- multiResultClass()
   result$result1 <- i+1
   result$result2 <- i+2
   return(result)
}
stopCluster(cl)

oper1 <- oper[[1]]$result1
oper2 <- oper[[1]]$result2
Run Code Online (Sandbox Code Playgroud)