您如何将global_rng状态写入文件,以便我可以加载它以备后用?

时间:2019-11-01 15:36:37

标签: random file-io julia

我有一个代码,运行时间很长,比集群上允许的最长挂墙时间更长。它依赖rand(),因此为了在集群上以多个顺序运行代码,我使用

julia> r = copy(Random.GLOBAL_RNG)

在运行结束时捕获全局随机数生成器的状态。我需要将'r'保存到文件中,然后在启动集群的下一次运行时从文件中读取该变量-本质上是为了能够“从我上次中断的地方接起”。当我尝试(使用软件包DelimitedFiles)时:

julia> writedlm("rngState.bin",r)

但是,出现以下错误

ERROR: MethodError: no method matching iterate(::MersenneTwister)
Closest candidates are:
  iterate(::Core.SimpleVector) at essentials.jl:568
  iterate(::Core.SimpleVector, ::Any) at essentials.jl:568
  iterate(::ExponentialBackOff) at error.jl:199

这使我相信Mersenne Twister rng的状态不是可以写入文件的状态。它是否正确?有人知道我如何将GLOBAL_RNG的状态保存到文件中,以便以后可以读回以取回我停下来的地方吗?

2 个答案:

答案 0 :(得分:1)

一种方法是使用内置标准库Serialization的功能:

julia> using Random, Serialization

julia> rng = MersenneTwister(); # create random generator

julia> rand(rng, 3)
3-element Array{Float64,1}:
 0.3708879403326799
 0.46672369641612566
 0.5728925387391

julia> open("out.bin", "w") do f
           serialize(f, rng) # serialize rng to file
       end

julia> rng_loaded = deserialize("out.bin"); # load & deserialize rng from file

julia> rand(rng, 3)
3-element Array{Float64,1}:
 0.6210629081706212
 0.8568331464134413
 0.7247872543135467

julia> rand(rng_loaded, 3) # same numbers
3-element Array{Float64,1}:
 0.6210629081706212
 0.8568331464134413
 0.7247872543135467

您可以使用相同的技术将Random.GLOBAL_RNG存储到文件中。设置它并不像Random.GLOBAL_RNG = rng_loaded那样琐碎,尽管您正试图在另一个模块中分配变量(不允许这样做)。但是,您可以使用copy!(Random.GLOBAL_RNG, rng_loaded)就地覆盖它。

请注意,序列化格式原则上可以在将来的Julia版本中更改。在这种情况下,您将无法再读取旧的rng文件。如果您打算将Rng存放更长的时间,请考虑将它们的各个字段存储在HDF5文件中。 (您可以找到一些灵感here。)

更新:如@Matt B在其答案中所示,用set_global_rng替换了我的愚蠢copy!函数。

答案 1 :(得分:1)

您正在尝试将RNG写入分隔的文件,但是其内部结构比简单的CSV可以支持的复杂得多。相反,我将使用序列化模块:

julia> using Random, Serialization

julia> open("rng.jls", "w") do f
           serialize(f, Random.GLOBAL_RNG)
       end

julia> rand(1, 5)
1×5 Array{Float64,2}:
 0.747507  0.279039  0.839956  0.265125  0.194283

julia> open("rng.jls") do f
           mt = deserialize(f)
           copy!(Random.GLOBAL_RNG, mt)
       end

julia> rand(1, 5)
1×5 Array{Float64,2}:
 0.747507  0.279039  0.839956  0.265125  0.194283