2011-12-02 11 views
18

Ho bisogno di fare alcune simulazioni e per scopi di debug voglio usare set.seed per ottenere lo stesso risultato. Ecco l'esempio di quello che sto cercando di fare:Come impostare i semi per le simulazioni casuali con i pacchetti foreach e 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)} 

Oggetti a e b dovrebbe essere identico, vale a dire sum(abs(a-b)) dovrebbe essere pari a zero, ma questo non è il caso. Sto facendo qualcosa di sbagliato o sono incappato in qualche caratteristica?

sono in grado di riprodurre questo su due sistemi diversi con R e R 2.13 2.14

risposta

17

La mia risposta predefinito utilizzato per essere "bene, allora non farlo" (usando foreach) come il pacchetto snow fa questo (affidabile!) per te.

Ma come sottolinea @Spacedman, il nuovo doRNG di Renaud è quello che stai cercando se desideri rimanere con la famiglia doFoo/foreach.

La vera chiave è una chiamata cluster in stile App per ottenere il set di semi su tutti i nodi. E in modo coordinato attraverso i flussi. Oh, e ho detto che lo snow di Tierney, Rossini, Li e Sevcikova ha fatto questo per voi per quasi un decennio?

Edit: E mentre non ha chiesto circa snow, per completezza ecco un esempio dalla riga di comando:

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

Edit: E per completezza, ecco il vostro esempio combinato con quello che è nella documentazione per 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

Grazie per esempio alla neve. Non sono esperto di complessità della programmazione parallela in R, quindi ho iniziato a usare 'foreach' per la sua transizione indolore da codice non parallelo a parallelo. Sapevo che mi mancava qualcosa. – mpiktas

+2

Beh, è ​​per questo che tutti abbiamo iniziato anni fa con la neve perché la transizione dalle funzioni standard * apply() a quelle parallele era semplice :) –

4

è il pacchetto doRNG alcuna utilità per voi? Ho il sospetto che il problema è dovuto a due thread sia Splatting casuale vettore seme:

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

+0

Grazie per la risposta, ho davvero vorrebbe segnare entrambi come risposta, ma la risposta di Dirk era più ampia. Ho comunque votato la tua risposta, dato che contiene abbastanza informazioni per risolvere il mio problema. – mpiktas

2

per cicli più complessi, potrebbe essere necessario includere set.seed() all'interno del ciclo 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 

contro

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

Utilizzando set.seed(123, kind = "L'Ecuyer-CMRG") fa anche il trucco e non richiede un pacchetto aggiuntivo:

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

Questa risposta è molto più semplice della risposta di Dirk Eddulbuettel. Ha qualche inconveniente? –

Problemi correlati