代码之家  ›  专栏  ›  技术社区  ›  akraf

为什么tempdir()在fork集群的每个核心上都给出相同的结果?

  •  3
  • akraf  · 技术社区  · 6 年前

    我想并行运行几个引导示例。计算包括为每个示例创建一个临时目录。我用这个包裹 future 具有 plan(multisession) ,它会自动在我的Linux计算机上创建一个fork集群来并行运行示例。

    我的问题是 tempdir() 不返回每个样本的不同结果,即使在 set.seed(.) 每个核心都不同。

    MCVE(这在Windows上不起作用,因为Windows不能 fork() ):

    clu <- parallel::makeForkCluster(4)
    unlist(parallel::clusterApply(clu, 1:4, 
      function(x){ set.seed(x); tempdir() }))
    ## [1] "/tmp/Rtmp0uaUin" "/tmp/Rtmp0uaUin" "/tmp/Rtmp0uaUin" "/tmp/Rtmp0uaUin"
    

    如果重新启动r,会得到不同的结果,但每个会话的返回值都是相等的。

    另一方面,其他随机函数也可以工作,至少如果我包括 set.seed(x)

    unlist(parallel::clusterApply(clu, x = 1:4, 
      function(x){ set.seed(x); rnorm(1) }))
    ##[1] -0.6264538 -0.8969145 -0.9619334  0.2167549
    
    unlist(parallel::clusterApply(clu, x = 1:4, 
      function(x){ rnorm(1) }))
    ## [1] -1.100044 -1.100044 -1.100044 -1.100044
    

    为什么 Twitter() 不同于其他随机函数的行为,对此我能做些什么?

    1 回复  |  直到 6 年前
        1
  •  3
  •   Ralf Stubner    6 年前

    引用 ?tempdir :

    […]在启动解释器之前创建每个会话的临时目录。

    所以最初的r过程修复并创建 tempdir() 分叉的进程继承了这一点。一种可能的解决方案是基于 tempfile() :

    unlist(parallel::mclapply(1:4, function(x){ tempfile(pattern = "dir") }))
    #> [1] "/tmp/Rtmpl1ynxV/dir42bb40fa8f75" "/tmp/Rtmpl1ynxV/dir42bc40fa8f75"
    #> [3] "/tmp/Rtmpl1ynxV/dir42bb2c930883" "/tmp/Rtmpl1ynxV/dir42bc2c930883"
    

    注意我正在使用 mclapply 因为这在默认情况下处理了RNG的种子设定。