我希望将模拟研究并行化以加快速度,并且我还想考虑重现性。特别是,我想获得与在顺序模拟运行开始时使用set.seed
的结果相同的结果。
以下是我尝试设置它的示例(我故意在这里使用.inorder=T
):
library(doSNOW)
library(rlecuyer)
nr.cores = 4
nr.simulations = 10
sample.size = 100000
seed = 12345
cl = makeCluster(nr.cores)
registerDoSNOW(cl)
clusterExport(cl=cl, list=c('sample.size'), envir=environment())
clusterSetupRNGstream(cl,rep(seed,6))
result = foreach(i=1:nr.simulations, .combine = 'c', .inorder=T)%dopar%{
tmp = rnorm(sample.size)
tmp[sample.size]
}
stopCluster(cl)
print(paste0('nr.cores = ',nr.cores,'; seed = ',seed,'; time =',Sys.time()))
print(result)
在多次运行此示例后,我有两个问题:
核心数会影响结果序列,例如nr.cores=1
和4
只有第一个值重合,nr.cores=4
和8
第一个值四个值重合。
有没有办法让它独立于nr.cores
?从概念上讲,我想我可以创建一个大小为nr.simulations * sample.size
的RNG流,将其拆分为nr.simulations
个并将它们按顺序分配给节点。更简单的是,我可以修复(不同)种子的nr.simulations
值,并再次以固定顺序将它们传递给节点。这可以通过某种节点映射来完成,节点映射可以由节点用于从表中读取其适当的种子值。有办法吗?
当我多次运行脚本时,它会发生(并非总是但不时),即使我没有更改任何参数(我只是反复获取文件),结果序列也会被重新排序。由于.inorder
或clusterSetupRNGstream
失败,这对我来说只是一个错误。或者我错过了什么?
[1] "nr.cores = 4; seed = 12345; time =2017-09-08 19:00:24"
[1] 1.327091137 -1.800244293 -1.163391460 0.005980001 0.957521136 1.641354433 -1.219033091
[8] -0.238129356 -0.225193384 1.457018576
[1] "nr.cores = 4; seed = 12345; time =2017-09-08 19:00:28"
[1] 1.327091137 -1.800244293 -1.163391460 0.005980001 -0.238129356 0.957521136 1.641354433
[8] -1.219033091 0.870269174 -0.225193384
答案 0 :(得分:1)
第一个问题:以下似乎对我有用
library(parallel)
library(doParallel)
cl <- makeCluster(5)
registerDoParallel(cl)
seedlist <- c(100, 200, 300, 400, 500)
clusterExport(cl, 'seedlist')
foreach(I=1:5) %dopar% {set.seed(seedlist[I]); runif(1)}
[[1]]
[1] 0.3077661
[[2]]
[1] 0.5337724
[[3]]
[1] 0.9152467
[[4]]
[1] 0.1499731
[[5]]
[1] 0.8336
set.seed(100)
runif(1)
[1] 0.3077661
第二个问题:看起来像个错误,但也许其他人有更好的线索
答案 1 :(得分:1)
所以,为了证明我的观点,.inorder
参数只是说你需要按顺序排列结果,而不是按顺序计算它们,你可以做
cl = makeCluster(nr.cores)
registerDoSNOW(cl)
replicate(10, {
foreach(ic = 1:8, .combine = 'c', .inorder = TRUE) %dopar% {
Sys.sleep(runif(1))
Sys.getpid()
}
})
stopCluster(cl)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 9252 9252 9252 9252 9252 9252 9252 9252 9252 9252
[2,] 9259 9259 9259 9259 9259 9259 9259 9259 9259 9259
[3,] 9266 9266 9266 9266 9266 9266 9266 9266 9266 9266
[4,] 9273 9273 9273 9273 9273 9273 9273 9273 9273 9273
[5,] 9273 9252 9259 9266 9273 9266 9252 9252 9266 9252
[6,] 9266 9266 9273 9273 9273 9259 9266 9259 9273 9266
[7,] 9266 9259 9252 9259 9259 9273 9273 9252 9259 9266
[8,] 9252 9252 9259 9266 9252 9252 9266 9252 9273 9259
嗯,不确定这真的证明了我的观点。它只是表明群集在开始时按顺序计算,然后是完成的第一个继续计算。
正如@Roland所建议的那样,您可以使用package doRNG来做您想做的事情。让我们验证一下:
library(doRNG)
cl = makeCluster(nr.cores)
registerDoSNOW(cl)
replicate(14, {
set.seed(12345)
sample.size = 100000
foreach(ic = 1:8, .combine = 'c', .inorder = TRUE) %dorng% {
Sys.sleep(runif(1))
tmp = rnorm(sample.size)
tmp[sample.size]
}
})
stopCluster(cl)
[,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,] 0.42281264 0.42281264 0.42281264 0.42281264 0.42281264 0.42281264 0.42281264
[2,] -1.67678339 -1.67678339 -1.67678339 -1.67678339 -1.67678339 -1.67678339 -1.67678339
[3,] -0.49011636 -0.49011636 -0.49011636 -0.49011636 -0.49011636 -0.49011636 -0.49011636
[4,] -0.87165416 -0.87165416 -0.87165416 -0.87165416 -0.87165416 -0.87165416 -0.87165416
[5,] -1.02636022 -1.02636022 -1.02636022 -1.02636022 -1.02636022 -1.02636022 -1.02636022
[6,] 0.56549835 0.56549835 0.56549835 0.56549835 0.56549835 0.56549835 0.56549835
[7,] 0.03998101 0.03998101 0.03998101 0.03998101 0.03998101 0.03998101 0.03998101
[8,] -0.38754750 -0.38754750 -0.38754750 -0.38754750 -0.38754750 -0.38754750 -0.38754750
[,8] [,9] [,10] [,11] [,12] [,13] [,14]
[1,] 0.42281264 0.42281264 0.42281264 0.42281264 0.42281264 0.42281264 0.42281264
[2,] -1.67678339 -1.67678339 -1.67678339 -1.67678339 -1.67678339 -1.67678339 -1.67678339
[3,] -0.49011636 -0.49011636 -0.49011636 -0.49011636 -0.49011636 -0.49011636 -0.49011636
[4,] -0.87165416 -0.87165416 -0.87165416 -0.87165416 -0.87165416 -0.87165416 -0.87165416
[5,] -1.02636022 -1.02636022 -1.02636022 -1.02636022 -1.02636022 -1.02636022 -1.02636022
[6,] 0.56549835 0.56549835 0.56549835 0.56549835 0.56549835 0.56549835 0.56549835
[7,] 0.03998101 0.03998101 0.03998101 0.03998101 0.03998101 0.03998101 0.03998101
[8,] -0.38754750 -0.38754750 -0.38754750 -0.38754750 -0.38754750 -0.38754750 -0.38754750