使用foreach()时使用循环计数器

时间:2014-10-27 12:11:08

标签: r foreach parallel-processing

我有一个大型模拟,我想在多个核心上运行。 为此,我使用foreach()包。

我正在迭代一个循环1000次并且在循环中我使用循环中的计数器作为位置向量,例如:

reps<-1000
for (i in reps){
a[i]<-mean(rnorm(100))
}

如果我对foreach做同样的事情:

library(foreach)
cl<-makeCluster(8)
registerDoParallel(cl)
ls<-foreach(icount(reps)) %dopar% {
rnorm(100)
}

我不能再使用原始循环中的当前计数器i。 有没有办法使用它?

我也有一个计数器,就像每次迭代过去一样,i = i + 1从i = 0开始。

1 个答案:

答案 0 :(得分:2)

正如罗兰所说,你可以将“foreach”版本写成:

reps <- 1000
ls <- foreach(i=icount(reps), .combine='c') %dopar% {
  mean(rnorm(100))
}

未使用变量i,但如果您将来需要它,则可以使用它。

在“foreach”循环中使用“for”循环对于获得更好的性能非常有用,因为它可以减少迭代次数并允许工作者并行完成更多的工作:

reps <- 1000
ls <- foreach(n=rep(reps/8, 8), .combine='c') %dopar% {
  a <- numeric(n)
  for (i in seq_len(n)) {
    a[i] <- mean(rnorm(100))
  }
  a
}

在“foreach”循环中对a进行赋值是很好的,因为它是一个局部变量。当“for”循环结束时,返回a,最后所有a向量与主人的“c”函数组合。

请注意,此示例在“foreach”循环中使用原始的“for”循环。这样做更有效率,因为主人不需要做很多工作来发送任务并收集和组合结果。

实际上,我会使用“sapply”代替“for”循环和“idiv”(来自“iterators”包)而不是“rep”:

reps <- 1000
ls <- foreach(n=idiv(reps, chunks=8), .combine='c') %dopar% {
  sapply(seq_len(n), function(i) mean(rnorm(100)))
}

对于“idiv”,如果迭代次数不能被工人数量整除,我不必担心会发生什么。