【问题标题】:Using counter from loop when using foreach()使用 foreach() 时使用循环中的计数器
【发布时间】:2014-10-27 12:11:07
【问题描述】:

我有一个大型模拟,我想在多个内核上运行。 为此,我使用了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=0 开始执行 i=i+1。

【问题讨论】:

  • foreach(i = seq_len(reps)) 然后你可以在循环中引用i。但是,请记住,您不会使用 foreach 循环分配给 a。相反,您将使用 .combine 参数并分配给您所显示的 ls
  • 但是如果我在 foreach 序列中有另一个 for 循环呢?我可以在那个循环中分配东西吗?
  • 当然可以。但是,您需要了解 foreach 循环的工作原理,即它们具有返回值。阅读foreach 小插曲。

标签: r foreach parallel-processing


【解决方案1】:

正如 Roland 所建议的,您可以将“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,最后由master将所有a向量与“c”函数结合起来。

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

实际上,我会使用“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”,我不必担心如果迭代次数不能被工作人员的数量整除会发生什么。

【讨论】:

    猜你喜欢
    • 2021-05-30
    • 2020-12-06
    • 2022-01-03
    • 2011-05-19
    • 2015-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    相关资源
    最近更新 更多