Random Julia聚类计算中的随机数种子

Random Julia聚类计算中的随机数种子,random,julia,random-seed,Random,Julia,Random Seed,我有一个Julia代码,我想通过并行运行大量作业(即大约10000个并行作业)将此代码提交给远程计算集群。这段代码的工作方式是,主函数(称之为“main.jl”)调用另一个函数(称之为“generator.jl”),该函数使用随机数,如rand(Float64)等。我通过bash文件提交main.jl,并通过包括 #PBS -t 1-N 我想确保我有一个不同的随机数发生器为每N份工作提交,但我不知道如何做到这一点。我在考虑根据环境变量设置一个随机种子;i、 例如,通过设置 @everywher

我有一个Julia代码,我想通过并行运行大量作业(即大约10000个并行作业)将此代码提交给远程计算集群。这段代码的工作方式是,主函数(称之为“main.jl”)调用另一个函数(称之为“generator.jl”),该函数使用随机数,如rand(Float64)等。我通过bash文件提交main.jl,并通过包括

#PBS -t 1-N
我想确保我有一个不同的随机数发生器为每N份工作提交,但我不知道如何做到这一点。我在考虑根据环境变量设置一个随机种子;i、 例如,通过设置

@everywhere import Random.Random
@everywhere using Random.Random

Random.seed!(ENV_VAR)
在main.jl中。但是,我不知道如何获取环境变量ENV_VAR。在MATLAB中,我知道我可以通过

NUM = getenv( 'PBS_ARRAYID' )
但我不知道如何在朱莉娅身上做到这一点。如果我在main.jl中设置了这个新的随机种子,那么每次bash脚本将main.jl提交到集群时,会生成不同的随机种子吗?同样,考虑到Julia RNG使用MersenneTwister,我甚至需要在Julia中这样做吗


为了以防万一,我一直在远程机器上使用Julia 1.5.1。

这里有两个问题:

  • 获取工作编号
  • 在随机数生成中使用作业编号
  • 每一个问题都有两个解决方案——一个更优雅,另一个不那么优雅,但也可以

    公元1年。 为了管理作业编号,请考虑使用PBS和代码>。那里有一个命令
    addprocs_pbs(np::Integer;qsub_flags=“”)
    ,可以从内部管理运行编号和编排集群。在许多情况下,您会发现这种方法更舒适。在这里,您可以使用种子设定随机数生成器(稍后将详细介绍)
    myid()
    ,该生成器返回工作者编号。无论如何,在这种情况下,您很可能会使用
    @distributed
    循环运行计算,并且您可以使用该值来设定RNG的种子。 如果您更倾向于通过bash脚本在外部编排数组作业,那么最好的方法可能是通过参数将作业编号传递给Julia进程,并从
    ARGS
    变量中读取,或者使用setup bash脚本导出可从
    ENV
    变量中读取的环境参数

    公元2年。 这里有两种方法。首先,您可以简单地在每个worker上创建一个新的MersseneTwister,然后在流中使用它。例如(这里我假设您使用某个变量
    jobid
    ):

    这基本上是正常的,并且已知随机流不相关。然而,您可能担心这种方法会给您的模拟引入一些工件。如果您想更加小心,可以使用单个随机流并将其划分为多个进程。这或许也是最先进的解决方案:

    using Random, Future
    rnd = Future.randjump(MersenneTwister(0), jobid*big(10)^20)
    

    这将使所有进程共享同一个巨大的随机数流(请注意,Mersenne Twister的状态为19937位,其周期为
    2^19937–1
    ,因此该跳转的大小一点也不大,
    big(10)^20
    是跳转的推荐步骤,因为它已经在
    randjump
    函数实现中预计算过了。

    相同的种子将给出相同的(随机)序列,因此作为种子的时间戳通常就足够了。问题是两种不同的种子是否可以相互依存;一个种子在一个序列中经过几个步骤后发生变化,就像由另一个种子启动一样。“我把这件事留给那些不那么懒得回答的人去做。”约佩金,我想我明白你的意思了。例如,我可以以毫秒为单位获取main.jl中的时间戳,然后将随机种子设置为该值。但是,如果我在.pbs文件中提交N个作业(如上述问题所述),其中至少有一些作业不会同时提交吗?由于生日悖论,这种情况经常会发生。你不能对集群中的随机数种子使用时间戳。@PrzemyslawSzufel是否有一种简单、安全的方法,可以在Julia中为每次提交的工作构建不同的随机种子,而不冒(多次)重复的风险?我正在为你写答案,耐心等待……我相信我现在看得更清楚了;非常感谢。但是,如何准确地获取唯一的jobid以便将其传递到ARGS中?例如,在我的.pbs脚本中,如果我有#pbs-t1-36,我应该将什么变量传递到ARGS以确保获得36个唯一的种子?我是否可以通过$PBS\u ARRAYID?我现在没有PBS要测试,但我相信您会在
    ENV[“PBS\u ARRAYID”]
    中找到这个值。您还可以考虑使用PBS启动BASH脚本,这将产生类似于<代码>朱丽亚Run.jl“${PBSjARARYID}”。从长远来看,使用ClusterMagaers.jl可能会更优雅;在ARGS中输入$PBS_ARRAYID可以实现这一点,并为Julia代码提供该作业的数值。最后一个问题:鉴于您上面使用Random和Future的示例,如果我设置Random.seed!(rnd)在定义rnd之后,无论何时我调用rand、randperm等。在这之后,我将自动使用该作业的种子,对吗?或者我必须担心generator.jl(哪个main.jl调用)中定义/使用的随机变量?我建议您拥有自己的
    MersenneTwister
    对象(
    rnd
    )并将其传递给您使用过的每个随机函数<代码>Random.seed!(rnd)执行不同的操作-将您的状态设置为系统时钟,这是您不想要的。
    using Random, Future
    rnd = Future.randjump(MersenneTwister(0), jobid*big(10)^20)