Как записать состояние global_rng в файл, чтобы я мог загрузить его для дальнейшего использования? - PullRequest
2 голосов
/ 01 ноября 2019

У меня есть код, который выполняется долго, дольше, чем максимально допустимое время ожидания в кластере. Он основан на 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 ]

1 голос
/ 01 ноября 2019

Вы пытаетесь записать ГСЧ в файл с разделителями, но его внутренняя структура гораздо сложнее, чем может поддерживать простой 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
1 голос
/ 01 ноября 2019

Одним из способов является использование функциональности встроенной стандартной библиотеки 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. Если вы планируете хранить файлы в течение более длительного периода времени, рассмотрите возможность сохранения их отдельных полей, например, в файле HDF5. (Вы можете найти вдохновение здесь .)

ОБНОВЛЕНИЕ: заменил мою глупую функцию set_global_rng на copy!, как указано @Matt B в его ответе.

...