2011-12-02 17 views
18

我需要做一些模擬和調試目的,我想用set.seed來獲得相同的結果。這裏是什麼,我試圖做的例子:如何使用foreach和doMC軟件包爲隨機模擬設置種子?

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)} 

對象ab應該是相同的,即sum(abs(a-b))應該爲零,但是這並非如此。我做錯了什麼,或者我偶然發現了某些功能?

我能夠有R 2.13和R 2.14

回答

17

我的默認回答「那麼不這樣做」(使用foreach) (可靠!)給你。

但正如@Spacedman指出的那樣,如果您想留在doFoo/foreach家族中,Renaud的新doRNG是您正在尋找的。

儘管真正的關鍵是通過clusterApply風格的調用來獲取在所有節點上設置的種子。並且以跨越流的方式進行協調。哦,我有沒有提到Tierney,Rossini,Li和Sevcikova的snow已經爲你做了近十年?

編輯:雖然你並沒有問snow,爲了完整性這裏是在命令行的例子:

[email protected]:~$ 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 
[email protected]:~$ 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 
[email protected]:~$ 

編輯:以及物品是否完整,這裏就是你們的榜樣合併什麼是在文檔爲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> 
+0

謝謝以雪爲例。我不熟悉R中並行編程的複雜性,所以我開始使用'foreach'從無並行代碼到並行的無痛轉換。我知道我錯過了一些東西。 – mpiktas

+2

好吧,這就是爲什麼我們都在幾年前開始下雪,因爲從標準* apply()函數轉換到並行函數很容易:) –

2

對於更復雜的循環,你可能要包括set.seed()內部的 for循環:

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 

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 
6

使用​​也做的伎倆,並且不需要額外的包:

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 
+0

這個答案比Dirk Eddulbuettel的答案簡單得多。它有什麼缺點嗎? –