Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unit tests broken under Julia 1.7 due to RNG change #121

Closed
tsj5 opened this issue Dec 2, 2021 · 2 comments
Closed

Unit tests broken under Julia 1.7 due to RNG change #121

tsj5 opened this issue Dec 2, 2021 · 2 comments
Assignees

Comments

@tsj5
Copy link
Collaborator

tsj5 commented Dec 2, 2021

Problem description

Running unit tests on a fresh installation of the master branch results in 3 failures: two in GaussianProcessEmulator, one in Utilities.

Steps to reproduce

Under arm64 julia 1.7.0 on macOS 12.0.1, julia --project -e 'using Pkg; Pkg.test()' gives

CLI output

(package dependency output omitted)

     Testing Running tests...
Starting tests for GaussianProcessEmulator
Using user-defined kernelType: SEIso{Float64}, Params: [0.0, 0.0]
Learning additive white noise
kernel in GaussianProcess
Type: SumKernel{SEIso{Float64}, Noise{Float64}}
  Type: SEIso{Float64}, Params: [0.0, 0.0]  Type: Noise{Float64}, Params: [0.0]
created GP1
optimized GP1
Type: SumKernel{SEIso{Float64}, Noise{Float64}}
  Type: SEIso{Float64}, Params: [0.4671112501592054, -0.11637219100301877]  Type: Noise{Float64}, Params: [-2.9126145297418646]
Using user-defined kernelType: SEIso{Float64}, Params: [0.0, 0.0]
Learning additive white noise
kernel in GaussianProcess
Type: SumKernel{SEIso{Float64}, Noise{Float64}}
  Type: SEIso{Float64}, Params: [0.0, 0.0]  Type: Noise{Float64}, Params: [0.0]
created GP1
optimized GP1
Type: SumKernel{SEIso{Float64}, Noise{Float64}}
  Type: SEIso{Float64}, Params: [-0.055491995428277534, -0.11637219133420702]  Type: Noise{Float64}, Params: [-2.912614529547923]
Using user-defined kernelType: SEIso{Float64}, Params: [0.0, 0.0]
Learning additive white noise
kernel in GaussianProcess
Type: SumKernel{SEIso{Float64}, Noise{Float64}}
  Type: SEIso{Float64}, Params: [0.0, 0.0]  Type: Noise{Float64}, Params: [0.0]
created GP1
optimized GP1
Type: SumKernel{SEIso{Float64}, Noise{Float64}}
  Type: SEIso{Float64}, Params: [0.4671112501592054, -0.11637219100301877]  Type: Noise{Float64}, Params: [-2.9126145297418646]
Using user-defined kernelPyObject 1**2 * RBF(length_scale=1)
Learning additive white noise
┌ Warning: `vendor()` is deprecated, use `BLAS.get_config()` and inspect the output instead
│   caller = npyinitialize() at numpy.jl:67
└ @ PyCall ~/.julia/packages/PyCall/3fwVL/src/numpy.jl:67
Tuple{String, String, Matrix{Float64}, Int64, Bool}[("k1__k1__constant_value", "numeric", [1.0e-5 100000.0], 1, 0), ("k1__k2__length_scale", "numeric", [1.0e-5 100000.0], 1, 0), ("k2__noise_level", "numeric", [1.0e-5 10.0], 1, 0)]
Completed training of: 1,
PyObject 1**2 * RBF(length_scale=1) + WhiteKernel(noise_level=1)
Using default squared exponential kernel, learning length scale and variance parameters
Using default squared exponential kernel: Type: SEArd{Float64}, Params: [-0.0, -0.0, 0.0]
Learning additive white noise
kernel in GaussianProcess
Type: SumKernel{SEArd{Float64}, Noise{Float64}}
  Type: SEArd{Float64}, Params: [-0.0, -0.0, 0.0]  Type: Noise{Float64}, Params: [0.0]
created GP1
optimized GP1
Type: SumKernel{SEArd{Float64}, Noise{Float64}}
  Type: SEArd{Float64}, Params: [-0.007517235204028216, 0.6725681044002463, 1.6206988182591024]  Type: Noise{Float64}, Params: [0.13855450266022618]
kernel in GaussianProcess
Type: SumKernel{SEArd{Float64}, Noise{Float64}}
  Type: SEArd{Float64}, Params: [-0.0, -0.0, 0.0]  Type: Noise{Float64}, Params: [0.0]
created GP2
optimized GP2
Type: SumKernel{SEArd{Float64}, Noise{Float64}}
  Type: SEArd{Float64}, Params: [2.003807044460205, 0.19558609424775078, 2.076620091667134]  Type: Noise{Float64}, Params: [0.3961207658931548]
GaussianProcessEmulator: Test Failed at /Users/tsj/Documents/climate/clima/CalibrateEmulateSample.jl/test/GaussianProcessEmulator/runtests.jl:156
  Expression: ≈(μ4[:, 1], [1.0, -1.0], atol = 0.25)
   Evaluated: [1.2975566836124686, -0.6760173440975431] ≈ [1.0, -1.0] (atol=0.25)
Stacktrace:
 [1] macro expansion
   @ /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Test/src/Test.jl:445 [inlined]
 [2] macro expansion
   @ ~/Documents/climate/clima/CalibrateEmulateSample.jl/test/GaussianProcessEmulator/runtests.jl:156 [inlined]
 [3] macro expansion
   @ /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Test/src/Test.jl:1283 [inlined]
 [4] top-level scope
   @ ~/Documents/climate/clima/CalibrateEmulateSample.jl/test/GaussianProcessEmulator/runtests.jl:18
GaussianProcessEmulator: Test Failed at /Users/tsj/Documents/climate/clima/CalibrateEmulateSample.jl/test/GaussianProcessEmulator/runtests.jl:157
  Expression: ≈(μ4[:, 2], [0.0, 2.0], atol = 0.25)
   Evaluated: [0.07893431381345757, 1.719842897385221] ≈ [0.0, 2.0] (atol=0.25)
Stacktrace:
 [1] macro expansion
   @ /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Test/src/Test.jl:445 [inlined]
 [2] macro expansion
   @ ~/Documents/climate/clima/CalibrateEmulateSample.jl/test/GaussianProcessEmulator/runtests.jl:157 [inlined]
 [3] macro expansion
   @ /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Test/src/Test.jl:1283 [inlined]
 [4] top-level scope
   @ ~/Documents/climate/clima/CalibrateEmulateSample.jl/test/GaussianProcessEmulator/runtests.jl:18
[10.0, 10.0]
Using default squared exponential kernel, learning length scale and variance parameters
Using default squared exponential kernel: Type: SEArd{Float64}, Params: [-0.0, -0.0, 0.0]
Learning additive white noise
kernel in GaussianProcess
Type: SumKernel{SEArd{Float64}, Noise{Float64}}
  Type: SEArd{Float64}, Params: [-0.0, -0.0, 0.0]  Type: Noise{Float64}, Params: [0.0]
created GP1
optimized GP1
Type: SumKernel{SEArd{Float64}, Noise{Float64}}
  Type: SEArd{Float64}, Params: [-0.007517235204081477, 0.6725681044001726, 1.6206988182589996]  Type: Noise{Float64}, Params: [0.13855450266022837]
kernel in GaussianProcess
Type: SumKernel{SEArd{Float64}, Noise{Float64}}
  Type: SEArd{Float64}, Params: [-0.0, -0.0, 0.0]  Type: Noise{Float64}, Params: [0.0]
created GP2
optimized GP2
Type: SumKernel{SEArd{Float64}, Noise{Float64}}
  Type: SEArd{Float64}, Params: [2.0038070444601424, 0.19558609424770934, 2.0766200916670297]  Type: Noise{Float64}, Params: [0.39612076589315587]
[10.0, 10.0]
SVD truncated at k:
1
Using default squared exponential kernel, learning length scale and variance parameters
Using default squared exponential kernel: Type: SEArd{Float64}, Params: [-0.0, -0.0, 0.0]
Learning additive white noise
kernel in GaussianProcess
Type: SumKernel{SEArd{Float64}, Noise{Float64}}
  Type: SEArd{Float64}, Params: [-0.0, -0.0, 0.0]  Type: Noise{Float64}, Params: [0.0]
created GP1
optimized GP1
Type: SumKernel{SEArd{Float64}, Noise{Float64}}
  Type: SEArd{Float64}, Params: [-0.007517235204081477, 0.6725681044001726, 1.6206988182589996]  Type: Noise{Float64}, Params: [0.13855450266022837]
Completed tests for GaussianProcessEmulator, 14 seconds elapsed
Starting tests for MarkovChainMonteCarlo
Using user-defined kernelType: SEIso{Float64}, Params: [0.0, 0.0]
Learning additive white noise
kernel in GaussianProcess
Type: SumKernel{SEIso{Float64}, Noise{Float64}}
  Type: SEIso{Float64}, Params: [0.0, 0.0]  Type: Noise{Float64}, Params: [0.0]
created GP1
optimized GP1
Type: SumKernel{SEIso{Float64}, Noise{Float64}}
  Type: SEIso{Float64}, Params: [0.3233234178772969, 1.2327884093595929]  Type: Noise{Float64}, Params: [-1.530975418436462]
[1.0]
[0.05;;]
[1.0]
[0.05;;]
Applying SVD to decorrelating outputs, if not required set svdflag=false
[4.47213595499958]
Begin step size search
iteration 0; current parameters [3.0;;]
iteration 2000; acceptance rate = 0.5037481259370314, current parameters [1.5038796982171492;;]
new step size: 1.0
iteration 2000; acceptance rate = 0.2783608195902049, current parameters [2.1140148346588017;;]
[1.0]
[0.05;;]
[1.0]
[0.05;;]
Applying SVD to decorrelating outputs, if not required set svdflag=false
[4.47213595499958]
[1.0]
[0.05;;]
[1.0]
[0.05;;]
Applying SVD to decorrelating outputs, if not required set svdflag=false
[4.47213595499958]
SVD truncated at k:
1
Using user-defined kernelType: SEIso{Float64}, Params: [0.0, 0.0]
Learning additive white noise
kernel in GaussianProcess
Type: SumKernel{SEIso{Float64}, Noise{Float64}}
  Type: SEIso{Float64}, Params: [0.0, 0.0]  Type: Noise{Float64}, Params: [0.0]
created GP1
optimized GP1
Type: SumKernel{SEIso{Float64}, Noise{Float64}}
  Type: SEIso{Float64}, Params: [0.32332341787964897, 1.2327884093598223]  Type: Noise{Float64}, Params: [-1.5309754184366229]
[1.0]
[0.05;;]
[0.1]
[0.0005;;]
Applying SVD to decorrelating outputs, if not required set svdflag=false
SVD truncated at k:
1
[4.47213595499958]
[1.0]
[0.05;;]
[1.0]
[0.05;;]
Applying SVD to decorrelating outputs, if not required set svdflag=false
[4.47213595499958]
Completed tests for MarkovChainMonteCarlo, 6 seconds elapsed
Starting tests for Utilities
Utilities: Test Failed at /Users/tsj/Documents/climate/clima/CalibrateEmulateSample.jl/test/Utilities/runtests.jl:21
  Expression: sample == [3.0, 3.0, 3.0]
   Evaluated: [1.0, 1.0, 1.0] == [3.0, 3.0, 3.0]
Stacktrace:
 [1] macro expansion
   @ /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Test/src/Test.jl:445 [inlined]
 [2] macro expansion
   @ ~/Documents/climate/clima/CalibrateEmulateSample.jl/test/Utilities/runtests.jl:21 [inlined]
 [3] macro expansion
   @ /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Test/src/Test.jl:1283 [inlined]
 [4] top-level scope
   @ ~/Documents/climate/clima/CalibrateEmulateSample.jl/test/Utilities/runtests.jl:13
[1.0, 1.0, 1.0]
Completed tests for Utilities, 1 seconds elapsed
Test Summary:             | Pass  Fail  Total
CalibrateEmulateSample    |   41     3     44
  GaussianProcessEmulator |   23     2     25
  MarkovChainMonteCarlo   |   10           10
  Utilities               |    8     1      9
ERROR: LoadError: Some tests did not pass: 41 passed, 3 failed, 0 errored, 0 broken.
in expression starting at /Users/tsj/Documents/climate/clima/CalibrateEmulateSample.jl/test/runtests.jl:16
ERROR: Package CalibrateEmulateSample errored during testing
Stacktrace:
 [1] pkgerror(msg::String)
   @ Pkg.Types /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Pkg/src/Types.jl:68
 [2] test(ctx::Pkg.Types.Context, pkgs::Vector{Pkg.Types.PackageSpec}; coverage::Bool, julia_args::Cmd, test_args::Cmd, test_fn::Nothing, force_latest_compatible_version::Bool, allow_earlier_backwards_compatible_versions::Bool, allow_reresolve::Bool)
   @ Pkg.Operations /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Pkg/src/Operations.jl:1672
 [3] test(ctx::Pkg.Types.Context, pkgs::Vector{Pkg.Types.PackageSpec}; coverage::Bool, test_fn::Nothing, julia_args::Cmd, test_args::Cmd, force_latest_compatible_version::Bool, allow_earlier_backwards_compatible_versions::Bool, allow_reresolve::Bool, kwargs::Base.Pairs{Symbol, Base.TTY, Tuple{Symbol}, NamedTuple{(:io,), Tuple{Base.TTY}}})
   @ Pkg.API /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Pkg/src/API.jl:421
 [4] test(pkgs::Vector{Pkg.Types.PackageSpec}; io::Base.TTY, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
   @ Pkg.API /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Pkg/src/API.jl:149
 [5] test(pkgs::Vector{Pkg.Types.PackageSpec})
   @ Pkg.API /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Pkg/src/API.jl:144
 [6] test(; name::Nothing, uuid::Nothing, version::Nothing, url::Nothing, rev::Nothing, path::Nothing, mode::Pkg.Types.PackageMode, subdir::Nothing, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
   @ Pkg.API /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Pkg/src/API.jl:164
 [7] test()
   @ Pkg.API /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Pkg/src/API.jl:158
 [8] top-level scope
   @ none:1

I haven't been able to verify that the tests in question pass on 1.6.x (since I'm on macOS, this involves installing intel-architecture versions of not only julia but the python dependencies, and I'm running into trouble rebuilding PyCall/ScikitLearn to pick everything up correctly).

Speculative diagnosis

The failures appear to be RNG-related:

  • the failure on l.21 of Utilities is due to get_obs_sample simply returning the wrong randomly selected observation.
  • I haven't investigated the GaussianProcess failures on l.156 and l.157, but they involve a model trained with noise_learn=true and comparisons with a large abs tolerance, so I'm suspecting the same cause. For what it's worth, the failing values aren't far outside tolerance.

Julia 1.7 changed the default RNG algorithm, but beyond that, the docs state that minor version changes may change the sequence of numbers returned from a given random seed due to internal implementation changes.

Proposed fix

A quick and dirty fix would be to monkey-patch Random in the unit tests and assign a MersenneTwister object (the algorithm used in julia 1.6 and earlier) to Random.GLOBAL_RNG. I've tried several constructions with copy! and eval, but haven't managed to do this.

Recommended best practice is to add an RNG argument to all functions that need to generate random variates, which allows reproducibility in terms of both seed and algorithm used. This shouldn't be painful from an end-user point of view, as the RNG object can be carried around in the top-level configuration object used in each stage.

Of course, proper MCMC convergence means aggregate statistics should be independent of the RNG sequence: this is only to guarantee reproducible tests.

@tsj5 tsj5 changed the title 3 unit tests broken under Julia 1.7 Unit tests broken under Julia 1.7 due to RNG change Dec 2, 2021
@tsj5
Copy link
Collaborator Author

tsj5 commented Dec 5, 2021

Speculation on the GaussianProcessEmulator above is incorrect: noise_learn=true and related settings only refer to covariance regularization. In both GaussianProcess.jl and ScikitLearn's implementation, regression is done by default with the L-BFGS algorithm, which is non-stochastic. My speculation is instead that the failed unit tests are due to changed training data used in the unit tests.

tsj5 added a commit to tsj5/CalibrateEmulateSample.jl that referenced this issue Dec 5, 2021
fixes CliMA#121

After fixing the RNG algorithm used, alter the parameters of broken
tests so that they pass.

- Increase number of training points and decrease noise covariance in
  GaussianProcessEmulator tests so that "Test case 2: 2D input, 2D
  output" passes.
- Change the sample observation compared against the return value of
  get_obs_sample() in Utilities tests.
@tsj5 tsj5 self-assigned this Jan 7, 2022
bors bot added a commit to CliMA/EnsembleKalmanProcesses.jl that referenced this issue Jan 22, 2022
95: Pass explicit RNG object to methods involving stochasticity r=ilopezgp a=tsj5

This is a rebase and squash of the feature branch for PR #81 and contains no new commits. The PR message for #81 is reproduced below.
<hr>
The motivation for this PR comes from CliMA/CalibrateEmulateSample.jl#121; see discussion there. 

In order to have reproducible tests involving randomness, it's not sufficient to set the global seed for the default RNG: the default RNG algorithm used by Julia was [changed](https://julialang.org/blog/2021/11/julia-1.7-highlights/#new_rng_reproducible_rng_in_tasks) in version 1.7, and the [docs](https://docs.julialang.org/en/v1/stdlib/Random/#Reproducibility) for the Random package note that the same seed may give different random values in different versions. For this reason, [recommended practice](https://discourse.julialang.org/t/set-the-state-of-the-global-rng/12599/3) for reproducible tests is to pass an RNG object explicitly to all methods which need it. Julia convention is that the RNG is an optional first positional argument in functions which require it (see e.g. Random, StatsBase, Turning.jl...), and this is done here.

This PR implements that change; in brief
- An `rng` field is added to `EnsembleKalmanProcesses` (i.e. independent of `Process`, for all implementations).
- An optional `rng` kwarg is added to `construct_initial_ensemble()`, used in lieu of `rng_seed` if provided.
- An additional method for `construct_initial_ensemble()` takes the rng as the first argument, causing kwargs to be ignored.
- All methods for `sample_distribution()` now accept an rng as an optional first argument.

In all of the cases above, `Random.GLOBAL_RNG` is used by default if an RNG is not given: this PR is fully backwards compatible with `main`. In particular, tests are updated to use an explicit rng, but examples have been left unchanged. It may be desirable to update them as well.



Co-authored-by: Thomas Jackson <tom.jackson314@gmail.com>
bors bot added a commit to CliMA/EnsembleKalmanProcesses.jl that referenced this issue Jan 22, 2022
95: Pass explicit RNG object to methods involving stochasticity r=ilopezgp a=tsj5

This is a rebase and squash of the feature branch for PR #81 and contains no new commits. The PR message for #81 is reproduced below.
<hr>
The motivation for this PR comes from CliMA/CalibrateEmulateSample.jl#121; see discussion there. 

In order to have reproducible tests involving randomness, it's not sufficient to set the global seed for the default RNG: the default RNG algorithm used by Julia was [changed](https://julialang.org/blog/2021/11/julia-1.7-highlights/#new_rng_reproducible_rng_in_tasks) in version 1.7, and the [docs](https://docs.julialang.org/en/v1/stdlib/Random/#Reproducibility) for the Random package note that the same seed may give different random values in different versions. For this reason, [recommended practice](https://discourse.julialang.org/t/set-the-state-of-the-global-rng/12599/3) for reproducible tests is to pass an RNG object explicitly to all methods which need it. Julia convention is that the RNG is an optional first positional argument in functions which require it (see e.g. Random, StatsBase, Turning.jl...), and this is done here.

This PR implements that change; in brief
- An `rng` field is added to `EnsembleKalmanProcesses` (i.e. independent of `Process`, for all implementations).
- An optional `rng` kwarg is added to `construct_initial_ensemble()`, used in lieu of `rng_seed` if provided.
- An additional method for `construct_initial_ensemble()` takes the rng as the first argument, causing kwargs to be ignored.
- All methods for `sample_distribution()` now accept an rng as an optional first argument.

In all of the cases above, `Random.GLOBAL_RNG` is used by default if an RNG is not given: this PR is fully backwards compatible with `main`. In particular, tests are updated to use an explicit rng, but examples have been left unchanged. It may be desirable to update them as well.



Co-authored-by: Thomas Jackson <tom.jackson314@gmail.com>
@tsj5
Copy link
Collaborator Author

tsj5 commented Feb 1, 2022

Closing issue, as the project currently targets only Julia 1.6 and can't support multiple minor versions at the same time, as described in #125. The above will be an issue when support is moved to some version > 1.6, so work will continue on PR #122.

@tsj5 tsj5 closed this as completed Feb 1, 2022
bors bot added a commit that referenced this issue Feb 4, 2022
122: [WIP] Use EKP.jl 0.2.0 & pass explicit RNG object where used r=odunbar a=tsj5

[*Edited 1 Feb 2022 in response to updates*] 

This PR updates CES to use the [0.2.0 release](https://github.com/CliMA/EnsembleKalmanProcesses.jl/releases/tag/v0.2.0) of EnsembleKalmanProcesses.jl (EKP). In addition to using changed module and method names, the PR adds support in CES for use of an explicit random number generator where needed; this was done in EKP [#81](CliMA/EnsembleKalmanProcesses.jl#81).

[Recommended practice](https://discourse.julialang.org/t/set-the-state-of-the-global-rng/12599/3) for reproducible tests is to pass an RNG object explicitly to all methods which need it. It's not sufficient to set the global seed for the default RNG: the default RNG algorithm used by Julia was [changed](https://julialang.org/blog/2021/11/julia-1.7-highlights/#new_rng_reproducible_rng_in_tasks) in version 1.7. This will affect us in the future when we update CES to support Julia > 1.6 (#121): the [docs](https://docs.julialang.org/en/v1/stdlib/Random/#Reproducibility) for the Random package note that the same seed may give different random values in different versions.

Changes made to the CES API in this PR are minor (which is why the RNG change is combined with the EKP update):
- An `rng` field is added to `MCMC`; the constructor sets this to `Random.GLOBAL_RNG` by default.
- `rng` is recognized as an optional first argument to `get_obs_sample`, used in lieu of the `rng_seed` kwarg if provided.

All changes are fully backwards compatible. In particular, tests are updated to use an explicit rng, but examples have been left unchanged. It may be desirable to update them as well.


Co-authored-by: Thomas Jackson <tom.jackson314@gmail.com>
bors bot added a commit that referenced this issue Feb 15, 2022
122: [WIP] Use EKP.jl 0.2.0 & pass explicit RNG object where used r=odunbar a=tsj5

[*Edited 1 Feb 2022 in response to updates*] 

This PR updates CES to use the [0.2.0 release](https://github.com/CliMA/EnsembleKalmanProcesses.jl/releases/tag/v0.2.0) of EnsembleKalmanProcesses.jl (EKP). In addition to using changed module and method names, the PR adds support in CES for use of an explicit random number generator where needed; this was done in EKP [#81](CliMA/EnsembleKalmanProcesses.jl#81).

[Recommended practice](https://discourse.julialang.org/t/set-the-state-of-the-global-rng/12599/3) for reproducible tests is to pass an RNG object explicitly to all methods which need it. It's not sufficient to set the global seed for the default RNG: the default RNG algorithm used by Julia was [changed](https://julialang.org/blog/2021/11/julia-1.7-highlights/#new_rng_reproducible_rng_in_tasks) in version 1.7. This will affect us in the future when we update CES to support Julia > 1.6 (#121): the [docs](https://docs.julialang.org/en/v1/stdlib/Random/#Reproducibility) for the Random package note that the same seed may give different random values in different versions.

Changes made to the CES API in this PR are minor (which is why the RNG change is combined with the EKP update):
- An `rng` field is added to `MCMC`; the constructor sets this to `Random.GLOBAL_RNG` by default.
- `rng` is recognized as an optional first argument to `get_obs_sample`, used in lieu of the `rng_seed` kwarg if provided.

All changes are fully backwards compatible. In particular, tests are updated to use an explicit rng, but examples have been left unchanged. It may be desirable to update them as well.


Co-authored-by: Thomas Jackson <tom.jackson314@gmail.com>
bors bot added a commit that referenced this issue Feb 16, 2022
122: [WIP] Use EKP.jl 0.2.0 & pass explicit RNG object where used r=tsj5 a=tsj5

[*Edited 1 Feb 2022 in response to updates*] 

This PR updates CES to use the [0.2.0 release](https://github.com/CliMA/EnsembleKalmanProcesses.jl/releases/tag/v0.2.0) of EnsembleKalmanProcesses.jl (EKP). In addition to using changed module and method names, the PR adds support in CES for use of an explicit random number generator where needed; this was done in EKP [#81](CliMA/EnsembleKalmanProcesses.jl#81).

[Recommended practice](https://discourse.julialang.org/t/set-the-state-of-the-global-rng/12599/3) for reproducible tests is to pass an RNG object explicitly to all methods which need it. It's not sufficient to set the global seed for the default RNG: the default RNG algorithm used by Julia was [changed](https://julialang.org/blog/2021/11/julia-1.7-highlights/#new_rng_reproducible_rng_in_tasks) in version 1.7. This will affect us in the future when we update CES to support Julia > 1.6 (#121): the [docs](https://docs.julialang.org/en/v1/stdlib/Random/#Reproducibility) for the Random package note that the same seed may give different random values in different versions.

Changes made to the CES API in this PR are minor (which is why the RNG change is combined with the EKP update):
- An `rng` field is added to `MCMC`; the constructor sets this to `Random.GLOBAL_RNG` by default.
- `rng` is recognized as an optional first argument to `get_obs_sample`, used in lieu of the `rng_seed` kwarg if provided.

All changes are fully backwards compatible. In particular, tests are updated to use an explicit rng, but examples have been left unchanged. It may be desirable to update them as well.


Co-authored-by: Thomas Jackson <tom.jackson314@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant