如何使用相同的种子产生相同的输出,在R中并行或不并行?

如何使用相同的种子产生相同的输出,在R中并行或不并行?,r,parallel-processing,R,Parallel Processing,例如,我需要从500个数字中随机选择10个 1:没有平行 133 186 286 452 101 445 467 326 310 31 2:并行 339 214 454 475 417 171 177 212 221 198 我使用了相同的种子,但得到了不同的结果。 如何使xxx1与xxx2相同?您正在为clusterSetRNGStream设置种子,这将帮助您为该函数的并行运行生成和复制相同的随机流集。它不会做你想做的事 您可能可以在函数中设置种子,以复制两个实现的输出。比如: # w/o p

例如,我需要从500个数字中随机选择10个

1:没有平行 133 186 286 452 101 445 467 326 310 31

2:并行 339 214 454 475 417 171 177 212 221 198

我使用了相同的种子,但得到了不同的结果。
如何使xxx1与xxx2相同?

您正在为clusterSetRNGStream设置种子,这将帮助您为该函数的并行运行生成和复制相同的随机流集。它不会做你想做的事

您可能可以在函数中设置种子,以复制两个实现的输出。比如:

# w/o parallel
set.seed(1)
xxx1 <- sample(1:500, 10)
print(xxx1)
# [1] 133 186 286 452 101 445 467 326 310  3

# w parallel
library("parallel")
cl <- makeCluster(1)
xxx2 <- parLapply(cl, 1, function(x) { set.seed(1); return(sample(1:500, 10)) })[[1]]
stopCluster(cl); rm(cl)
print(xxx2)
# [1] 133 186 286 452 101 445 467 326 310  3
并行RNG例如Parallel::clusterSetRNGStream使用L'Ecuyer-CMRG方法。顺序RNG默认为Mersenne捻线器方法,参见RNGkind。也可以在顺序模式下使用L'Ecuyer-CMRG RNG流,但我认为正确使用它会有点乏味。无论您做什么,都不要在并行模式下使用非并行RNG

免责声明:我是作者。该软件包将允许您生成相同的并行RNG,无论您使用的是顺序处理还是并行处理。您将得到完全相同的结果。这同样适用于所有类型的并行后端以及您使用的并行辅助进程的数量。比如说,

library(future.apply)

plan(sequential) # default
set.seed(1)
y0 <- future_lapply(1:3, function(x) sample(1:500, 10), future.seed = TRUE)

plan(multisession) # PSOCK cluster == parallel::makeCluster()
set.seed(1)
y1 <- future_lapply(1:3, function(x) sample(1:500, 10), future.seed = TRUE)
stopifnot(identical(y1, y0))

plan(multisession, workers = 2)
set.seed(1)
y2 <- future_lapply(1:3, function(x) sample(1:500, 10), future.seed = TRUE)
stopifnot(identical(y2, y0))

plan(multisession, workers = 3)
set.seed(1)
y3 <- future_lapply(1:3, function(x) sample(1:500, 10), future.seed = TRUE)
stopifnot(identical(y3, y0))

plan(multicore)  ## forked processing == parallel::mclapply()
set.seed(1)
y4 <- future_lapply(1:3, function(x) sample(1:500, 10), future.seed = TRUE)
stopifnot(identical(y4, y0))

plan(future.callr::callr)  ## background R session via callr package
set.seed(1)
y5 <- future_lapply(1:3, function(x) sample(1:500, 10), future.seed = TRUE)
stopifnot(identical(y5, y0))

我不确定这是否可能。您可以确保并行版本在运行两次时输出相同的结果,但我认为您无法确保获得与顺序版本相同的输出。我能想到的唯一解决方案是在不进行任何其他计算的情况下运行一次采样,并获得与每个块关联的种子。
# w/o parallel
set.seed(1)
xxx1 <- sample(1:500, 10)
print(xxx1)
# [1] 133 186 286 452 101 445 467 326 310  3

# w parallel
library("parallel")
cl <- makeCluster(1)
xxx2 <- parLapply(cl, 1, function(x) { set.seed(1); return(sample(1:500, 10)) })[[1]]
stopCluster(cl); rm(cl)
print(xxx2)
# [1] 133 186 286 452 101 445 467 326 310  3
library(future.apply)

plan(sequential) # default
set.seed(1)
y0 <- future_lapply(1:3, function(x) sample(1:500, 10), future.seed = TRUE)

plan(multisession) # PSOCK cluster == parallel::makeCluster()
set.seed(1)
y1 <- future_lapply(1:3, function(x) sample(1:500, 10), future.seed = TRUE)
stopifnot(identical(y1, y0))

plan(multisession, workers = 2)
set.seed(1)
y2 <- future_lapply(1:3, function(x) sample(1:500, 10), future.seed = TRUE)
stopifnot(identical(y2, y0))

plan(multisession, workers = 3)
set.seed(1)
y3 <- future_lapply(1:3, function(x) sample(1:500, 10), future.seed = TRUE)
stopifnot(identical(y3, y0))

plan(multicore)  ## forked processing == parallel::mclapply()
set.seed(1)
y4 <- future_lapply(1:3, function(x) sample(1:500, 10), future.seed = TRUE)
stopifnot(identical(y4, y0))

plan(future.callr::callr)  ## background R session via callr package
set.seed(1)
y5 <- future_lapply(1:3, function(x) sample(1:500, 10), future.seed = TRUE)
stopifnot(identical(y5, y0))