问题

我正在try 实现一个可重现的多核模拟,并获得不一致的结果.请帮助我解释这些结果,并建议我实施这一点的正确方法.请注意,我正在研究WSL2(不过,我希望我的结果还有其他原因).

细节

每个并行任务生成随机数,并被动态分配到一个可用的核(与预先调度到核相反).根据documentation,这可以通过使用parallel::mclapply中的mc.preschedule=FALSE来实现.为了保证可重复性,在设置随机种子时,任务应独立于分配给它们的 node 生成相同的随机数.

try 的解决方案

我的 idea 是使用RNGkind("L'Ecuyer-CMRG")parallel::nextRNGStream for each task分配一个单独的(独立的)随机数流.以下代码段生成与这些流关联的种子列表,每个任务有一个列表条目.

library(parallel)
RNGkind("L'Ecuyer-CMRG")
n <- 100  # number of tasks

set.seed(1)
seeds <- list(.Random.seed)
for (i in 2:n) {
  seeds[[i]] <- nextRNGStream(seeds[[i - 1]])
}

现在的 idea 是,每个任务在开始生成随机数之前设定它的种子.我使用函数f来表示一些任务.

f <- function(i, seeds) {
  .Random.seed <- seeds[[i]]
  rnorm(1)
}

结果不一致

我希望任务的结果与parallel::mclapply中的参数mc.set.seed无关,因为这些任务无论如何都会设置自己的种子.然而,正如在这里可以观察到的那样,情况并非如此:

cores <- 2  # set to more than one
r1 <- mclapply(1:n, f, seeds=seeds, mc.preschedule=FALSE, mc.cores=cores, mc.set.seed=TRUE)
r2 <- mclapply(1:n, f, seeds=seeds, mc.preschedule=FALSE, mc.cores=cores, mc.set.seed=FALSE)
cat("r1: ", sum(unlist(r1)), "\n")
cat("r2: ", sum(unlist(r2)), "\n")
# r1:  24.39407 
# r2:  46.08108

此外,我预计这些任务将生成相同的随机数,无论它们是串行执行还是并行执行.情况也并非如此:

r3 <- mclapply(1:n, f, seeds=seeds, mc.preschedule=FALSE, mc.set.seed=FALSE, mc.cores=1)
cat("r3: ", sum(unlist(r3)), "\n")
# r3:  -7.079515

为什么会出现这些结果,实施这一结果的正确方式是什么?

推荐答案

您正在一个函数中设置.Random.seed <- seeds[[i]].这设置了一个局部变量,而不是全局随机种子.用.Random.seed <<- seeds[[i]]代替,它应该会起作用.

"超级赋值"运算符<<-查看父环境,直到它找到与该名称匹配的现有变量,并在那里进行赋值.如果它没有找到,它会在全球环境中进行分配.这意味着在正常情况下,它将修复您的问题,但您可能会意外地拥有另一个名为.Random.seed的变量,该变量将首先被找到,在这种情况下,它将无法工作.所以别那么做.

R相关问答推荐

如何创建具有总计列和ggplot 2所有条线的百分比标签的堆叠条形图?

在ubuntu 22.04上更新到R4.4后包安装出现编译错误

为什么以及如何修复Mapview不显示所有点并且st_buffer合并一些区域R?

terra nearest()仅为所有`to_id`列返回NA

如何按排序顺序打印一个框架中所有精确的唯一值?

隐藏e_mark_line的工具提示

如何从R中的字符串元素中减go 一个数字?

删除具有相同标题的tabPanel(shinly)

如何使用STAT_SUMMARY向ggplot2中的密度图添加垂直线

非线性混合效应模型(NLME)预测变量的置信区间

如何同时从多个列表中获取名字?

2个Rscript.exe可执行文件有什么区别?

如何在R库GoogleDrive中完全删除预先授权的Google帐户?

按时间顺序对不同事件进行分组

派生程序包| ;无法检索';return()';的正文

如何在R中改变fviz_pca_biplot中圆的边界线的 colored颜色 ?

有没有办法一次粘贴所有列

对R中的列表列执行ROW Mean操作

需要一个函数来在第一行创建一个新变量,然后用新变量替换一个不同的变量(对于多行)

按两个条件自动过滤数据