我有一个代码,运行时间很长,比集群上允许的最长挂墙时间更长。它依赖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的状态保存到文件中,以便以后可以读回以取回我停下来的地方吗?
答案 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