首页 > 解决方案 > 用于 Julia 集群计算的随机数种子

问题描述

我有一个 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。

标签: randomjuliarandom-seed

解决方案


这里有两个问题:

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

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

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

广告 2。这里有两种方法。首先,您可以简单地在每个工作人员处创建一个新的 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 位,并且是 19937 位的周期,2^19937 – 1所以这个跳转的大小一点也不大,big(10)^20是跳转的推荐步骤,因为它已经在randjump函数实现中预先计算)。


推荐阅读