2011-12-02 12 views
18

Necesito hacer algunas simulaciones y para fines de depuración quiero usar set.seed para obtener el mismo resultado. Aquí está el ejemplo de lo que estoy tratando de hacer:Cómo establecer la semilla para simulaciones aleatorias con los paquetes foreach y 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)} 

Objetos a y b deben ser idénticos, es decir sum(abs(a-b)) debe ser cero, pero este no es el caso. Estoy haciendo algo mal, ¿o me he tropezado con alguna función?

soy capaz de reproducir esto en dos sistemas diferentes con R y R 2,13 2,14

Respuesta

17

Mi respuesta por defecto que solía ser "bien entonces no haga que" (usando foreach) como el paquete snow hace esto (¡confiablemente!) para ti.

Pero como señala @Spacedman, la nueva doRNG de Renaud es lo que está buscando si desea permanecer con la familia doFoo/foreach.

La clave real es un clúster. Aplicar una llamada de estilo para obtener las semillas establecidas en todos los nodos. Y de una manera que coordina a través de las transmisiones. Ah, ¿y mencioné que snow de Tierney, Rossini, Li y Sevcikova ha estado haciendo esto por usted durante casi una década?

Editar: Y mientras usted no solicitó sobre snow, para lo completo Este es un ejemplo de la línea de comandos:

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

Editar: Y para completar, aquí está el ejemplo combinada con lo que se encuentra en los documentos de 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

Gracias por ejemplo con nieve. No estoy muy versado en las complejidades de la programación paralela en R, así que comencé a usar 'foreach' para su transición indolora de código no paralelo a paralelo. Sabía que me estaba perdiendo algo. – mpiktas

+2

Bueno, es por eso que todos comenzamos hace años con la nieve, ya que la transición de las funciones estándar * apply() a las paralelas fue fácil :) –

4

es el paquete doRNG ninguna utilidad para usted? Sospecho que el problema se debe a dos hilos tanto splatting el vector de inicialización aleatorio:

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

+0

Gracias por su respuesta, realmente Me hubiera gustado marcar ambos como una respuesta, pero la respuesta de Dirk fue más extensa. No obstante, he votado a favor de tu respuesta, ya que contiene suficiente información para resolver mi problema. – mpiktas

2

para bucles más complicados, es posible que tenga que incluir set.seed() en el interior del bucle 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 

frente

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

Usando set.seed(123, kind = "L'Ecuyer-CMRG") también hace el truco y no requiere un paquete adicional:

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

Esta respuesta es mucho más simple que la respuesta de Dirk Eddulbuettel. ¿Tiene algún inconveniente? –

Cuestiones relacionadas