【发布时间】:2021-11-11 12:45:55
【问题描述】:
我有一个外部 foreach/dopar 并行循环,其中包含一个内部循环。内部循环的每个实例都应该在同一组随机数上工作。其余部分,即外部主体的其余部分和并行实例应该照常工作,即使用独立的随机数。
我可以在非并行实现中实现这一点,方法是在内循环开始之前保存 RNG 的状态,并在执行内循环的每个实例后恢复此状态。请参阅以下示例:
library(doSNOW)
seed = 4711
cl = makeCluster(2)
registerDoSNOW(cl)
clusterSetupRNGstream (cl, seed=rep(seed,6))
erg = foreach(irun = 1:3,.combine = rbind) %dopar% {
#do some random stuff in outer loop
smp = runif(1)
# save current state of RNG
s = .Random.seed
# inner loop, does some more random stuff
idx = numeric(5)
for(ii in seq.int(5)) {
idx[ii] = sample.int(10, 1)
# reset RNG for next loop iteration
set.seed(s)
}
c(smp,idx)
}
> print(erg)
[,1] [,2] [,3] [,4] [,5] [,6]
result.1 0.5749162 7 6 2 3 7
result.2 0.1208910 4 3 6 8 9
result.3 0.3491315 7 2 7 6 10
我想要的输出是每行的常量整数,每行都不同。所以这不能并行工作。原因很清楚:snow 使用了不同的随机生成器(rlecuyer)并且必须处理并行流。
问题是:如何使用随机数生成器 rlecuyer 实现雪中种子的重置?对我来说,挑战之一是在何时重置种子时确定正确的子流。
我目前的解决方法是为内部循环预先计算所有随机数据(在示例中为 idx 向量),然后在所有内部实例中使用此常量数据。这不是最优的,因为随机数据总体上变得非常大,并且以较小的块动态(重新)生成它要好得多。
编辑
任何设置/重置都保持并行流独立是最重要的。据我目前了解这需要的机制:
在每个并行进程内:
- 检测进程正在处理的相关子流。
- 在方便的时候:查找并存储此子流的随机种子。
- 在方便的时候:使用 2) 中的种子重置 1) 的子流,并保持所有其他流不受干扰。
【问题讨论】:
标签: r random parallel-processing montecarlo snow