diff options
| author | Sebastian Berg <sebastianb@nvidia.com> | 2023-02-13 09:10:42 +0100 |
|---|---|---|
| committer | Sebastian Berg <sebastianb@nvidia.com> | 2023-02-14 20:19:28 +0100 |
| commit | e390f6772766c3b27711ef3ab5df498dd7494d45 (patch) | |
| tree | 62938f299104111daab7705e707514b4af26fbb3 | |
| parent | 6f1d159cb711fcbd8240abd7fd68415d8319c4d9 (diff) | |
| download | numpy-e390f6772766c3b27711ef3ab5df498dd7494d45.tar.gz | |
DOC: Improve docs around generator spawning
Trying to address Robert Kerns review comments.
| -rw-r--r-- | doc/source/reference/random/bit_generators/index.rst | 12 | ||||
| -rw-r--r-- | doc/source/reference/random/generator.rst | 5 | ||||
| -rw-r--r-- | numpy/random/_generator.pyx | 45 | ||||
| -rw-r--r-- | numpy/random/bit_generator.pyx | 29 |
4 files changed, 74 insertions, 17 deletions
diff --git a/doc/source/reference/random/bit_generators/index.rst b/doc/source/reference/random/bit_generators/index.rst index d93f38d0b..f67458567 100644 --- a/doc/source/reference/random/bit_generators/index.rst +++ b/doc/source/reference/random/bit_generators/index.rst @@ -50,6 +50,8 @@ The included BitGenerators are: Philox <philox> SFC64 <sfc64> +.. _seeding_and_entropy: + Seeding and Entropy =================== @@ -127,6 +129,16 @@ of 12 instances: .. end_block +If you already have an initial random generator instance, you can shorten +the above by using the `~Generator.spawn` method: + +.. code-block:: python + + from numpy.random import PCG64, SeedSequence + # High quality initial entropy + entropy = 0x87351080e25cb0fad77a44a3be03b491 + base_rng = PCG(entropy) + generators = base_rng.spawn(12) An alternative way is to use the fact that a `~SeedSequence` can be initialized by a tuple of elements. Here we use a base entropy value and an integer diff --git a/doc/source/reference/random/generator.rst b/doc/source/reference/random/generator.rst index dc71cb1f9..e08395b17 100644 --- a/doc/source/reference/random/generator.rst +++ b/doc/source/reference/random/generator.rst @@ -18,12 +18,13 @@ can be changed by passing an instantized BitGenerator to ``Generator``. :members: __init__ :exclude-members: __init__ -Accessing the BitGenerator --------------------------- +Accessing the BitGenerator and Spawning +--------------------------------------- .. autosummary:: :toctree: generated/ ~numpy.random.Generator.bit_generator + ~numpy.random.Generator.spawn Simple random data ------------------ diff --git a/numpy/random/_generator.pyx b/numpy/random/_generator.pyx index dd2952083..6cf0d976e 100644 --- a/numpy/random/_generator.pyx +++ b/numpy/random/_generator.pyx @@ -242,12 +242,7 @@ cdef class Generator: """ Create new independent child generators. - This is a convenience method to safely spawn new random number - generators via the `numpy.random.SeedSequence.spawn` mechanism. - The original seed sequence is used by the bit generator and accessible - as ``Generator.bit_generator.seed_seq``. - - Please see `numpy.random.SeedSequence` for additional notes on + See :ref:`seeding_and_entropy` for additional notes on seeding and spawning children. .. versionadded:: 1.25.0 @@ -256,6 +251,42 @@ cdef class Generator: ------- child_generators : list of Generators + Raises + ------ + TypeError + When the underlying SeedSequence does not implement spawning. + + See Also + -------- + random.BitGenerator.spawn, random.SeedSequence.spawn : + Equivalent method on the bit generator and seed sequence. + bit_generator : + The bit generator instance used by the generator. + + Examples + -------- + Starting from a seeded default generator: + + >>> # High quality entropy created with: f"0x{secrets.randbits(128):x}" + >>> entropy = 0x3034c61a9ae04ff8cb62ab8ec2c4b501 + >>> rng = np.random.default_rng(entropy) + + Create two new generators for example for parallel executation: + + >>> child_rng1, child_rng2 = rng.spawn(2) + + Drawn numbers from each are independent but derived from the initial + seeding entropy: + + >>> rng.uniform(), child_rng1.uniform(), child_rng2.uniform() + (0.19029263503854454, 0.9475673279178444, 0.4702687338396767) + + It is safe to spawn additional children from the original ``rng`` or + the children: + + >>> more_child_rngs = rng.spawn(20) + >>> nested_spawn = child_rng1.spawn(20) + """ return [type(self)(g) for g in self._bit_generator.spawn(n_children)] @@ -4846,6 +4877,8 @@ def default_rng(seed=None): ----- If ``seed`` is not a `BitGenerator` or a `Generator`, a new `BitGenerator` is instantiated. This function does not manage a default global instance. + + See :ref:`seeding_and_entropy` for more information about seeding. Examples -------- diff --git a/numpy/random/bit_generator.pyx b/numpy/random/bit_generator.pyx index acee0edf7..32d24c20d 100644 --- a/numpy/random/bit_generator.pyx +++ b/numpy/random/bit_generator.pyx @@ -458,6 +458,12 @@ cdef class SeedSequence(): Returns ------- seqs : list of `SeedSequence` s + + See Also + -------- + random.Generator.spawn, random.BitGenerator.spawn : + Equivalent method on the generator and bit generator. + """ cdef uint32_t i @@ -571,12 +577,9 @@ cdef class BitGenerator(): """ Create new independent child bit generators. - This is a convenience method to safely spawn new random number - generators via the `numpy.random.SeedSequence.spawn` mechanism. - The original seed sequence is accessible as ``bit_generator.seed_seq``. - - Please see `numpy.random.SeedSequence` for additional notes on - spawning children. + See :ref:`seeding_and_entropy` for additional notes on seeding and + spawning children. Some bit generators also implement ``jumped`` + as a different approach for creating independent streams. .. versionadded:: 1.25.0 @@ -584,12 +587,20 @@ cdef class BitGenerator(): ------- child_bit_generators : list of BitGenerators + Raises + ------ + TypeError + When the underlying SeedSequence does not implement spawning. + + See Also + -------- + random.Generator.spawn, random.SeedSequence.spawn : + Equivalent method on the generator and seed sequence. + """ if not isinstance(self._seed_seq, ISpawnableSeedSequence): raise TypeError( - "The underlying SeedSequence does not implement spawning. " - "You must ensure a custom SeedSequence used for initializing " - "the random state implements spawning (and registers it).") + "The underlying SeedSequence does not implement spawning.") return [type(self)(seed=s) for s in self._seed_seq.spawn(n_children)] |
