1

我正在使用 R 中的 doParallel/Foreach 后端并行运行一个进程。我将一组 20 个内核注册为一个集群,并运行该进程大约 100 次。我将一个矩阵传递给并行过程的每次迭代,并在子过程中将矩阵替换为它自己行的随机样本。我想知道的是:我是否应该期望这种修改在同一个子进程处理的后续迭代中持续存在?例如,当子进程 1 完成第一次迭代时,它是使用原始矩阵还是随机样本开始第二次迭代?

一个最小的例子:

   library(doParallel)

   X <- matrix(1:400, ncol=4)

   cl<-makeCluster(2)
   clusterExport(X)
   registerDoParallel(cl)


   results<-foreach(i=1:100) %dopar% {
       set.seed(12345)
       X <- X[sample.int(nrow(X),replace=TRUE),]
       X
   }

编辑:

需要明确的是,如果该对象确实会在同一个工作进程的迭代中持续存在,这不是我想要的行为。相反,我希望每次迭代都采用原始矩阵的新随机样本,而不是最近随机样本的随机样本(我认识到,在我的最小示例中,它每次都会创建原始矩阵的相同随机样本,由于种子集——在我的实际应用程序中,我处理了这个)。

4

1 回答 1

1

集群工作者中的副作用在 foreach 循环的迭代中持续存在是可能的,但这不是 foreach 支持的特性。利用它的程序可能无法移植到不同的并行后端,并且可能无法与较新版本的软件一起使用。事实上,我在第一次写 foreach 的时候就试图让这种副作用变得不可能,但我最终还是放弃了。

请注意,在您的情况下,您并没有修改X明确导出给工作人员的副本:您正在修改由 doParallel 自动导出给工作人员的副本。这可能是你困惑的根源。

如果你真的想这样做,我建议你关闭自动导出,X然后修改显式导出的副本,以便程序应该定义良好且可移植,虽然有点难看。这是一个例子:

library(doParallel)
cl <- makePSOCKcluster(2)
registerDoParallel(cl)
X <- matrix(0, nrow=4, ncol=4)
clusterExport(cl, 'X')
ignore <- clusterApply(cl, seq_along(cl), function(i) ID <<- i)
results <-
  foreach(i=1:4, .noexport='X') %dopar% {
    X[i,] <<- ID
    X
  }
finalresults <- clusterEvalQ(cl, X)

results包含每个任务之后的矩阵,并finalresults在 foreach 循环完成后包含每个工人的矩阵。


更新

通常,foreach 循环的主体不应修改 foreach 循环之外的任何变量。我只修改我之前在 foreach 循环的同一迭代中创建的变量。如果要制作仅在该迭代中使用的修改版本,请使用不同的变量名称。

于 2016-10-11T16:09:54.693 回答