【问题标题】:How to set seeds when using parallel package in R在R中使用并行包时如何设置种子
【发布时间】:2019-10-30 18:12:27
【问题描述】:

我目前在 R 中使用 parallel 包,我正在尝试通过设置种子来使工作可重现。

但是,如果您在创建集群之前设置种子并并行执行您想要的任务,出于某种原因,它不会使其可重现。我想我需要在制作集群时为每个核心设置种子。

我在这里做了一个小例子来说明我的问题:

library(parallel)

# function to generate 2 uniform random numbers
runif_parallel <- function() {
  # make cluster of two cores
  cl <- parallel::makeCluster(2)

  # sample uniform random numbers
  samples <- parallel::parLapplyLB(cl, X = 1:2, fun = function(i) runif(1))

  # close cluster
  parallel::stopCluster(cl)

  return(unlist(samples))
}

set.seed(41)
test1 <- runif_parallel()

set.seed(41)
test2 <- runif_parallel()

# they should be the same since they have the same seed
identical(test1, test2)

在此示例中,test1test2 应该相同,因为它们具有相同的种子,但它们返回不同的结果。

请问我哪里出错了?

请注意,我编写此示例的方式必须模仿我现在的使用方式 - 可能有更简洁的方法可以并行生成两个随机统一数。

【问题讨论】:

  • 在函数(i)中设置种子

标签: r parallel-processing


【解决方案1】:

您需要在每个作业中运行set.seed。 这是一个可重现的随机生成:

cl <- parallel::makeCluster(2)

# sample uniform random numbers
parallel::clusterEvalQ(cl, set.seed(41));

samples <- parallel::parLapplyLB(cl, X = 1:2, fun = function(i){set.seed(i);runif(1)})
samples

# [[1]]
# [1] 0.2655087
# 
# [[2]]
# [1] 0.1848823

samples <- parallel::parLapplyLB(cl, X = 1:2, fun = function(i){set.seed(i);runif(1)})
samples

# [[1]]
# [1] 0.2655087
# 
# [[2]]
# [1] 0.1848823

parallel::stopCluster(cl)

【讨论】:

  • 有没有一种方法可以为所有内核设置种子?我实际上在关闭集群之前做了很多功能,所以我想我的例子并没有完全重现我的问题
  • 您可以在每个作业中使用此行设置相同的随机种子:parallel::clusterEvalQ(cl, set.seed(41))
  • 由于函数中的set.seed(i) 部分和set.seed(41) 部分不影响此处的随机化,它们在此代码中产生相同的结果。我想我需要一个解决方案,为每个核心设置不同的种子
  • 警告:在并行处理中生成可靠的统计随机数需要非常小心,并且正确处理非常重要,尤其是在进行统计分析时。让某些东西工作起来很容易(就像这里建议的那样),但这并不意味着它就是你想要的方式。您想使用 L'Ecuyer 的 RNG 之类的东西,参见。 ?parallel::RNGstreams。如果你使用foreach(),你可以使用doRNG。 future.apply::future_lapply(..., future.seed=TRUE) 也将为您完成。
  • @HenrikB 谢谢!我发现这个资源也有帮助:s3.amazonaws.com/assets.datacamp.com/production/course_6245/…
【解决方案2】:

如果它可能有帮助,一种为每个核心设置单独种子的快速方法

# Set number of cores, here to n-1
nCores <- parallel::detectCores()-1

# Parallelization, n-1 cores
parallel::setDefaultCluster(cl = (cl <- parallel::makeCluster(nCores)))

thisSeed <- 1
# Set different seeds in each cluster; here set to 1 for the cluster, 2 for the second, etc. 
# Do something in each cluster
(parRes <- do.call(c, parallel::clusterApply(x = 1:nCores+thisSeed-1, fun = function(x) {
  set.seed(x)
  runif(1)
  })))

# Stop cluster
stopCluster(cl = cl)

# Same thing, not in parallel
singleRes <- do.call(c, lapply(1:nCores+thisSeed-1, function(x) {
  set.seed(x)
  runif(1)
}))

# Verify that the results are the same
all(parRes == singleRes)

【讨论】:

    猜你喜欢
    • 2021-03-31
    • 2021-08-11
    • 2013-01-01
    • 2022-11-28
    • 2015-06-17
    • 2016-04-13
    • 2020-08-05
    • 1970-01-01
    • 2016-04-02
    相关资源
    最近更新 更多