2014-10-27 128 views
2

我有一个很大的仿真,我想在多个内核上运行。 为此,我正在使用foreach()包。使用foreach时使用循环计数器()

我迭代循环1000次,并在循环中,我使用从环路的位置矢量计数器,用于exampe:

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 + 1从i = 0开始。

+0

'foreach(i = seq_len(reps))'然后你可以在循环中引用'i'。但是,请记住,您不会使用'foreach'循环来分配'a'。相反,您会使用'.combine'参数并在您显示时分配给'ls'。 – Roland 2014-10-27 12:25:15

+0

但如果我在foreach序列中有另一个for循环呢?我可以在该循环中分配事物吗? – user1723765 2014-10-27 12:29:23

+1

当然可以。但是,您需要了解“foreach”循环的工作方式,即它们具有返回值。阅读'foreach'小插曲。 – Roland 2014-10-27 12:48:14

回答

2

罗兰建议,你可以写“的foreach”版本:

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

变量i没有使用,但如果你想在将来它的可用。

使用“为”内部“的foreach”循环回路可用于获取更好的性能是非常有用的,因为它可以减少迭代次数,并允许工人做更多的工作并行:

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”(从“迭代”包),而不是“代表”:

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

随着“IDIV”我不如果迭代次数不能被工人数量整除,就不必担心会发生什么。