用于 Julia 集群计算的随机数种子

Random number seeds for Julia cluster computing

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

并行 运行 N 个作业
#PBS -t 1-N

我想确保为 N 个作业提交中的每一个都使用不同的随机数生成器,但我不确定如何执行此操作。我正在考虑根据环境变量设置一个随机种子;即,通过设置

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

Random.seed!(ENV_VAR)

在 main.jl 中。但是,我不确定如何获取环境变量 ENV_VAR。在 MATLAB 中,我知道我可以通过

NUM = getenv( 'PBS_ARRAYID' )

但我不知道如何在 Julia 中执行此操作。如果我设法在 main.jl 中设置这个新的随机种子,每次 bash 脚本向集群提交 main.jl 时,这会生成不同的随机种子吗?同样,考虑到 Julia RNG 使用 MersenneTwister,我什至需要在 Julia 中执行此操作吗?

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

这里有两个问题:

  1. 获取职位编号
  2. 在随机数生成中使用作业编号。

这些问题中的每一个都有两个解决方案 - 一个更优雅,另一个不太优雅,但也可以。

广告 1。 要管理作业编号,请考虑将 PBS 与 ClusterManagers.jl 一起使用。那里有一个命令 addprocs_pbs(np::Integer; qsub_flags="") 可以管理 运行 数字并从 Julia 内部编排集群。在许多情况下,您会发现这种方法更舒服。在这里,您可以使用 returns 工人编号 myid() 作为随机数生成器的种子(稍后会详细介绍)。无论如何,您很可能会在这种情况下 运行 使用 @distributed 循环进行计算,并且您可以使用该值作为 RNG 的种子。 如果您更愿意通过 bash 脚本在外部编排数组作业,那么最好的办法可能是通过参数将作业编号传递给 Julia 进程并从 ARGS 变量中读取它,或者设置 bash 导出可从 ENV 变量中读取的环境参数的脚本。

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

using Random
rnd = MersenneTwister(jobid)
rand(rnd, 4)

这基本上没问题,并且已知随机流不相关。但是,您可能会担心这种方法会给您的模拟带来一些瑕疵。如果您想更加小心,可以使用单个随机流并将其划分到多个进程中。这也许也是最先进的解决方案:

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

这将使所有进程共享相同的巨大随机数流(请注意,Mersenne Twister 的状态是 19937 位,并且是 2^19937 – 1 的周期,因此这种跳跃的大小根本不是很大 big(10)^20 是跳转的推荐步骤,因为它已经在 randjump 函数实现中预先计算好了。