我有一个大型模拟,我想在多个核心上运行。
为此,我使用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开始。
答案 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”,如果迭代次数不能被工人数量整除,我不必担心会发生什么。