Как установить seed для случайного моделирования с помощью пакетов foreach и doMC? - PullRequest
22 голосов
/ 02 декабря 2011

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

Ответы [ 4 ]

18 голосов
/ 02 декабря 2011

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

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

Реальный ключ - это вызов типа clusterApply, чтобы получить начальные числа, установленные на всех узлах. И таким образом, который координируется между потоками. О, и я упоминал, что снег Тирни, Россини, Ли и Севчикова делал это для вас почти десятилетие?

Edit: И хотя вы не спрашивали о snow , для полноты вот пример из командной строки:

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

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

Использование 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 голосов
/ 02 декабря 2011

Вам полезен пакет doRNG?Я подозреваю, что ваша проблема связана с тем, что два потока разделяют случайный начальный вектор:

2 голосов
/ 13 декабря 2016

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