gpt4 book ai didi

使用 Snow/doSNOW 为内循环重置 R 随机数生成器 (rlecuyer)

转载 作者:行者123 更新时间:2023-12-04 11:29:12 26 4
gpt4 key购买 nike

我有一个包含内部循环的外部 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) 的子流,并使所有其他流不受干扰。
  • 最佳答案

    这里有几件事值得一提。
    首先,您正在保存 .Random.seed然后将其直接传递给 set.seed ,
    即使您没有遇到 RNG 问题,这也不会给您想要的结果。
    这样做的原因是,正如所记录的那样,set.seedseed参数只关心一个整数,
    所以如果你传递一个向量,
    它仍然只会使用第一个值,
    以及 .Random.seed 的文档状态:

    .Random.seed is an integer vector whose first element codes the kind of RNG and normal generator.


    所以你所有的并行流都会以相同的整数结束,因为 .Random.seed 的第一个值对于相同的 RNG 类型总是相同的。
    其次,文档还指出:

    .Random.seed saves the seed set for the uniform random-number generator, at least for the system generators. It does not necessarily save the state of other generators, and in particular does not save the state of the Box–Muller normal generator. If you want to reproduce work later, call set.seed (preferably with explicit values for kind and normal.kind) rather than set .Random.seed.


    这意味着如果您要操纵更多内部值,您绝对应该知道您使用的是什么 RNG。
    如果您拨打 clusterEvalQ(cl, RNGkind())在您调用 clusterSetupRNGstream 后,
    你会看到它返回:
    [1] "user-supplied" "Inversion"     "Rejection"
    所以你不能假设 .Random.seed将足以保存 RNG 的状态。
    事实上,我什至不确定它是否与 doSNOW 配合得很好。 ,
    看到这个差异:
    clusterSetupRNGstream(cl, seed = rep(seed, 6))
    foo = foreach(irun = 1:2, .combine = list) %dopar% {
    list(
    .Random.seed,
    get(".Random.seed", .GlobalEnv)
    )
    }
    > str(foo)
    List of 2
    $ :List of 2
    ..$ : int [1:626] 10403 1 -921191862 -372998484 563067311 -15494811 985677596 1278354290 1696669677 -1382461401 ...
    ..$ : int 10405
    $ :List of 2
    ..$ : int [1:626] 10403 1 -921191862 -372998484 563067311 -15494811 985677596 1278354290 1696669677 -1382461401 ...
    ..$ : int 10405
    最后,从您的示例中可以清楚地看出 set.seed在这种情况下并没有真正起作用。 clusterSetupRNGstream 的文档声明 rlecuyer包被使用,
    我对这个包的了解不够详细,无法说明它是否支持 set.seed或不,
    但我想不会。
    我可以给你的唯一选择是我之前使用过的一个更冗长的选择:
    RNGkind("L'Ecuyer-CMRG")

    cl = makeCluster(2)
    registerDoSNOW(cl)

    seed = 4711L
    set.seed(seed)
    # x is a vector of length irun - 1
    seeds = Reduce(x = 1:2, init = .Random.seed, accumulate = TRUE, f = function(x, ignored) {
    parallel::nextRNGStream(x)
    })

    erg = foreach(pseed = seeds, .combine = rbind) %dopar% {
    RNGkind("L'Ecuyer-CMRG")
    assign(".Random.seed", pseed, .GlobalEnv)

    # do some random stuff in outer loop
    smp = runif(1)

    # save current state of RNG
    s = get(".Random.seed", .GlobalEnv)

    # 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
    assign(".Random.seed", s, .GlobalEnv)
    }

    c(smp, idx)
    }

    > print(erg)
    [,1] [,2] [,3] [,4] [,5] [,6]
    result.1 0.9482966 2 2 2 2 2
    result.2 0.1749918 3 3 3 3 3
    result.3 0.3263343 1 1 1 1 1
    AFAIK,R 自己的 L'Ecuyer-CMRG 的状态确实在 .Random.seed 中举行.

    关于使用 Snow/doSNOW 为内循环重置 R 随机数生成器 (rlecuyer),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69209872/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com