diff --git a/nifty6/minimization/metric_gaussian_kl_mpi.py b/nifty6/minimization/metric_gaussian_kl_mpi.py index 24bd12980654218af6ba1917b475a3062367944c..537397302c5f4f323ec74af13b6ba54f51aa224b 100644 --- a/nifty6/minimization/metric_gaussian_kl_mpi.py +++ b/nifty6/minimization/metric_gaussian_kl_mpi.py @@ -128,8 +128,7 @@ class MetricGaussianKL_MPI(Energy): def __init__(self, mean, hamiltonian, n_samples, constants=[], point_estimates=[], mirror_samples=False, - napprox=0, _samples=None, - lh_sampling_dtype=np.float64): + napprox=0, _samples=None, lh_sampling_dtype=np.float64): super(MetricGaussianKL_MPI, self).__init__(mean) if not isinstance(hamiltonian, StandardHamiltonian): diff --git a/nifty6/random.py b/nifty6/random.py index cb4566ba9a1d3db3442875192b7c5e0f710577a4..244dd1da795def2a3d55184c35e048c569528973 100644 --- a/nifty6/random.py +++ b/nifty6/random.py @@ -15,6 +15,60 @@ # # NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik. +""" +Some remarks on NIFTy's treatment of random numbers + +NIFTy makes use of the `Generator` and `SeedSequence` classes introduced to +`numpy.random` in numpy 1.17. + +On first load of the `nifty6.random` module, it creates a stack of +`SeedSequence` objects which contains a single `SeedSequence` with a fixed seed, +and also a stack of `Generator` objects, which contains a single generator +derived from the above seed sequence. Without user intervention, this generator +will be used for all random number generation tasks within NIFTy. This means + +- that random numbers drawn by NIFTy will be reproducible across multiple runs + (assuming there are no complications like MPI-enabled runs with a varying + number of tasks), and +- that trying to change random seeds via `numpy.random.seed` will have no + effect on the random numbers drawn by NIFTy. + +Users who want to change the random seed for a given run can achieve this +by calling `push_sseq_from_seed()` with a seed of their choice. This will push +a new seed sequence generated from tat seed onto the seed sequence stack, and a +generator derived from this seed sequence onto the generator stack. Since all +NIFTy RNG-related calls will use the generator on the top of the stack, all +calls from this point on wil use the new generator. +If the user already has a `SeedSequence` object at hand, they can pass this to +NIFTy via `push_sseq`. A new generator derived from this sequence will then also +be pushed onto the generator stack. +These operations can be reverted (and should be, as soon as the new generator is +no longer needed) by a call to `pop_sseq()`. +When users need diect access to the RNG currently in use, they can access it +via the `current_rng` function. + + +Example for using multiple seed sequences: + +Assume that N samples are needed to compute a KL, which are distributed over +a variable number of MPI tasks. In this situation, whenever random numbers +need to be drawn for these samples: +- each MPI task should spawn as many seed sequences as there are samples + _in total_, using `sseq = spawn_sseq(N)` +- each task loops over the local samples + - first pushing the seed sequence for the global(!) index of the + current sample via `push_sseq(sseq[iglob])` + - drawing the required random numbers + - then popping the seed sequence again via `pop_sseq()` + +That way, random numbers should be reproducible and independent of the number +of MPI tasks. + +WARNING: do not push/pop the same `SeedSequence` object more than once - this +will lead to repeated random sequences! Whenever you have to push `SeedSequence` +objects, generate new ones via `spawn_sseq()`. +""" + import numpy as np # Stack of SeedSequence objects. Will always start out with a well-defined diff --git a/test/test_random.py b/test/test_random.py index c075bc9d915ba3476c60ae2ea21e0f62c5ccb892..842d1ca7e1b2b10ac436be9a03afff91adb65f0c 100644 --- a/test/test_random.py +++ b/test/test_random.py @@ -1,3 +1,20 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# Copyright(C) 2020 Max-Planck-Society +# +# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik. + import numpy as np import nifty6 as ift