在我看来,如果您想保证 R 会话中对 mclapply 的后续调用获得不同的随机数,您需要使用不同的值调用 set.seed,删除全局变量“.Random.seed”,或生成在再次调用 mclapply 之前,该 R 会话中至少有一个随机数。
出现此行为的原因是 mclapply(与 mcparallel 不同)在内部调用 mc.reset.stream。这会将“parallel”包中隐藏的种子重置为“.Random.seed”的值,因此,如果再次调用 mclapply 时“.Random.seed”没有更改,则由 mclapply 启动的工作程序将获得与之前相同的随机数。
请注意,clusterApply 和 parLapply 等函数的情况并非如此,因为它们使用持久工作线程,因此会继续从 RNG 流中抽取随机数。但每次调用 mclapply 时都会有新的工作线程被分叉,这可能会让这种行为变得更加困难。
以下是使用 mclapply 将种子设置为不同值以便获取不同随机数的示例:
RNGkind("L'Ecuyer-CMRG")
set.seed(100)
mclapply(1:2, function(i) rnorm(2))
set.seed(101)
mclapply(1:2, function(i) rnorm(2))
以下是删除“.Random.seed”的示例:
RNGkind("L'Ecuyer-CMRG")
mclapply(1:2, function(i) rnorm(2))
rm(.Random.seed)
mclapply(1:2, function(i) rnorm(2))
这是在主机上生成随机数的示例:
RNGkind("L'Ecuyer-CMRG")
mclapply(1:2, function(i) rnorm(2))
rnorm(1)
mclapply(1:2, function(i) rnorm(2))
我不确定哪种方法是最好的方法,但这可能取决于您想要做什么。
尽管看起来简单地多次调用 mclapply 而不更改“.Random.seed”会产生可重现的结果,但我不知道这是否得到保证。为了保证可重现的结果,我认为你需要调用 set.seed:
RNGkind("L'Ecuyer-CMRG")
set.seed(1234)
mclapply(1:2, function(i) rnorm(2))
set.seed(1234)
mclapply(1:2, function(i) rnorm(2))