如何使用foreach和doMC包为随机模拟设置种子?

mpi*_*tas 23 parallel-processing r random-forest

我需要做一些模拟和调试,我想set.seed用来获得相同的结果.这是我想要做的例子:

library(foreach)
library(doMC)
registerDoMC(2)

set.seed(123)
a <- foreach(i=1:2,.combine=cbind) %dopar% {rnorm(5)}
set.seed(123)
b <- foreach(i=1:2,.combine=cbind) %dopar% {rnorm(5)}
Run Code Online (Sandbox Code Playgroud)

对象ab应该是相同的,即sum(abs(a-b))应该为零,但是这并非如此.我做错了什么,或者我偶然发现了一些功能?

我能够在R 2.13和R 2.14的两个不同系统上重现这一点

Dir*_*tel 18

我的默认答案曾经是"好然后不要那样做"(使用foreach),因为snow包为你做(可靠!).

但正如@Spacedman指出的那样,如果你想留在/ foreach家族,Renaud的新doRNG就是你正在寻找的.doFoo

真正的密钥是clusterApply样式调用,用于在所有节点上设置种子.并以一种跨流协调的方式.哦,我提到被蒂尔尼,罗西尼,李和Sevcikova已经这样做了你快十年了?

编辑:虽然你没有询问,但为了完整性,这里是命令行的一个例子:

edd@max:~$ r -lsnow -e'cl <- makeSOCKcluster(c("localhost","localhost"));\
         clusterSetupRNG(cl);\
         print(do.call("rbind", clusterApply(cl, 1:4, \
                                             function(x) { stats::rnorm(1) } )))'
Loading required package: utils
Loading required package: utils
Loading required package: rlecuyer
           [,1]
[1,] -1.1406340
[2,]  0.7049582
[3,] -0.4981589
[4,]  0.4821092
edd@max:~$ r -lsnow -e'cl <- makeSOCKcluster(c("localhost","localhost"));\
         clusterSetupRNG(cl);\
         print(do.call("rbind", clusterApply(cl, 1:4, \
                                             function(x) { stats::rnorm(1) } )))'
Loading required package: utils
Loading required package: utils
Loading required package: rlecuyer
           [,1]
[1,] -1.1406340
[2,]  0.7049582
[3,] -0.4981589
[4,]  0.4821092
edd@max:~$ 
Run Code Online (Sandbox Code Playgroud)

编辑:为了完整起见,这里结合了doRNG文档中的内容

> library(foreach)
R> library(doMC)
Loading required package: multicore

Attaching package: ‘multicore’

The following object(s) are masked from ‘package:parallel’:

    mclapply, mcparallel, pvec

R> registerDoMC(2)
R> library(doRNG)
R> set.seed(123)
R> a <- foreach(i=1:2,.combine=cbind) %dopar% {rnorm(5)}
R> set.seed(123)
R> b <- foreach(i=1:2,.combine=cbind) %dopar% {rnorm(5)}
R> identical(a,b)
[1] FALSE                     ## ie standard approach not reproducible
R>
R> seed <- doRNGseed()
R> a <- foreach(i=1:2,combine=cbind) %dorng% { rnorm(5) }
R> b <- foreach(i=1:2,combine=cbind) %dorng% { rnorm(5) }
R> doRNGseed(seed)
R> a1 <- foreach(i=1:2,combine=cbind) %dorng% { rnorm(5) }
R> b1 <- foreach(i=1:2,combine=cbind) %dorng% { rnorm(5) }
R> identical(a,a1) && identical(b,b1)
[1] TRUE                      ## all is well now with doRNGseed()
R> 
Run Code Online (Sandbox Code Playgroud)

  • 好吧,这就是为什么我们都开始多年前的雪,因为从标准*apply()函数到并行函数的过渡很容易:) (2认同)

enr*_*ero 8

使用set.seed(123, kind = "L'Ecuyer-CMRG")也可以做到这一点,并且不需要额外的包:

set.seed(123, kind = "L'Ecuyer-CMRG")
a <- foreach(i=1:2,.combine=cbind) %dopar% {rnorm(5)}
b <- foreach(i=1:2,.combine=cbind) %dopar% {rnorm(5)}
identical(a,b)
# TRUE
Run Code Online (Sandbox Code Playgroud)

  • 我也被这个解决方案的简单性所吸引,但我无法重现结果(在 Windows 7 上使用 R 3.4.0、`doParallel` 1.0.11 和 `foreach` 1.4.3) (2认同)

Spa*_*man 5

doRNG 包对你有用吗?我怀疑您的问题是由于两个线程都散布随机种子向量:

http://ftp.heanet.ie/mirrors/cran.r-project.org/web/packages/doRNG/index.html


K B*_*Bro 5

对于更复杂的循环,您可能必须在for 循环内包含 set.seed() :

library(foreach)
library(doMC)
registerDoMC(2)
library(doRNG)

set.seed(123)
a <- foreach(i=1:2,.combine=cbind) %dopar% {
  create_something <- c(1, 2, 3)
  rnorm(5)
}
set.seed(123)
b <- foreach(i=1:2,.combine=cbind) %dopar% {
  create_something  <- c(4, 5, 6)
  rnorm(5)
}
identical(a, b)
# FALSE
Run Code Online (Sandbox Code Playgroud)

相对

a <- foreach(i=1:2,.combine=cbind) %dopar% {
  create_something  <- c(1, 2, 3)
  set.seed(123)
  rnorm(5)
}
b <- foreach(i=1:2,.combine=cbind) %dopar% {
  create_something  <- c(4, 5, 6)
  set.seed(123)
  rnorm(5)
}
identical(a, b)
# TRUE
Run Code Online (Sandbox Code Playgroud)