Подтвердить что ты не робот

Как установить семена для случайного моделирования с пакетами foreach и doMC?

Мне нужно сделать некоторые симуляции, и для целей отладки я хочу использовать 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)}

Объекты a и b должны быть одинаковыми, т.е. sum(abs(a-b)) должен быть равен нулю, но это не так. Я делаю что-то не так, или я наткнулся на какую-то особенность?

Я могу воспроизвести это на двух разных системах с R 2.13 и R 2.14

4b9b3361

Ответ 1

Мой ответ по умолчанию был "хорошо, тогда не делайте этого" (используя foreach) как snow делает это (надежно!) для вас.

Но, как указывает @Spacedman, Renaud new doRNG - это то, что вы ищете, если хотите остаться с doFoo/foreach.

Настоящий ключ, однако, является вызовом типа clusterApply, чтобы получить семена, установленные на всех узлах. И в моде, которая координировалась через потоки. О, и я упомянул, что 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]:~$ 

Edit: И для полноты, вот ваш пример в сочетании с тем, что находится в документах для 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> 

Ответ 2

Использование 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

Ответ 4

Для более сложных циклов вам может потребоваться включить 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