Skip to content

Commit

Permalink
Revert "MAINT: Implement API changes for randomgen-derived code"
Browse files Browse the repository at this point in the history
This reverts commit 17e0070.
  • Loading branch information
bashtage authored and mattip committed May 27, 2019
1 parent 3db5a77 commit 58c0e72
Showing 36 changed files with 10,205 additions and 94 deletions.
8 changes: 4 additions & 4 deletions benchmarks/benchmarks/bench_random.py
Original file line number Diff line number Diff line change
@@ -86,8 +86,8 @@ def time_permutation_int(self):

class RNG(Benchmark):
param_names = ['rng']
params = ['DSFMT', 'MT19937', 'Xoshiro256', 'Xoshiro512',
'Philox', 'ThreeFry', 'numpy']
params = ['DSFMT', 'PCG64', 'PCG32', 'MT19937', 'Xoshiro256',
'Xoshiro512', 'Philox', 'ThreeFry', 'numpy']

def setup(self, brng):
if brng == 'numpy':
@@ -128,8 +128,8 @@ class Bounded(Benchmark):
u32 = np.uint32
u64 = np.uint64
param_names = ['rng', 'dt_max']
params = [['DSFMT', 'MT19937','Xoshiro256', 'Xoshiro512',
'Philox', 'ThreeFry', 'numpy'],
params = [['DSFMT', 'PCG64', 'PCG32', 'MT19937','Xoshiro256',
'Xoshiro512', 'Philox', 'ThreeFry', 'numpy'],
[[u8, 95],
[u8, 64], # Worst case for legacy
[u8, 127], # Best case for legacy
8 changes: 5 additions & 3 deletions doc/source/reference/random/bit_generators/index.rst
Original file line number Diff line number Diff line change
@@ -5,11 +5,11 @@ Bit Generators

.. currentmodule:: numpy.random

The random values produced by :class:`~Generator`
The random values produced by :class:`~Generator`
orignate in a BitGenerator. The BitGenerators do not directly provide
random numbers and only contains methods used for seeding, getting or
setting the state, jumping or advancing the state, and for accessing
low-level wrappers for consumption by code that can efficiently
setting the state, jumping or advancing the state, and for accessing
low-level wrappers for consumption by code that can efficiently
access the functions provided, e.g., `numba <https://numba.pydata.org>`_.

Stable RNGs
@@ -20,6 +20,8 @@ Stable RNGs

DSFMT <dsfmt>
MT19937 <mt19937>
PCG32 <pcg32>
PCG64 <pcg64>
Philox <philox>
ThreeFry <threefry>
Xoshiro256** <xoshiro256>
34 changes: 34 additions & 0 deletions doc/source/reference/random/bit_generators/pcg32.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
Parallel Congruent Generator (32-bit, PCG32)
--------------------------------------------

.. module:: numpy.random.pcg32

.. currentmodule:: numpy.random.pcg32

.. autoclass:: PCG32
:exclude-members:

Seeding and State
=================

.. autosummary::
:toctree: generated/

~PCG32.seed
~PCG32.state

Parallel generation
===================
.. autosummary::
:toctree: generated/

~PCG32.advance
~PCG32.jumped

Extending
=========
.. autosummary::
:toctree: generated/

~PCG32.cffi
~PCG32.ctypes
34 changes: 34 additions & 0 deletions doc/source/reference/random/bit_generators/pcg64.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
Parallel Congruent Generator (64-bit, PCG64)
--------------------------------------------

.. module:: numpy.random.pcg64

.. currentmodule:: numpy.random.pcg64

.. autoclass:: PCG64
:exclude-members:

Seeding and State
=================

.. autosummary::
:toctree: generated/

~PCG64.seed
~PCG64.state

Parallel generation
===================
.. autosummary::
:toctree: generated/

~PCG64.advance
~PCG64.jumped

Extending
=========
.. autosummary::
:toctree: generated/

~PCG64.cffi
~PCG64.ctypes
1 change: 1 addition & 0 deletions doc/source/reference/random/index.rst
Original file line number Diff line number Diff line change
@@ -168,6 +168,7 @@ The included BitGenerators are:
`Random123`_ page for more details about this class of bit generators.

.. _`dSFMT authors' page`: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/
.. _`PCG author's page`: http://www.pcg-random.org/
.. _`xorshift, xoroshiro and xoshiro authors' page`: http://xoroshiro.di.unimi.it/
.. _`Random123`: https://www.deshawresearch.com/resources_random123.html

4 changes: 2 additions & 2 deletions doc/source/reference/random/legacy.rst
Original file line number Diff line number Diff line change
@@ -19,8 +19,8 @@ are produced in pairs. It is important to use
.. warning::

:class:`~randomgen.legacy.LegacyGenerator` only contains functions
that have changed. Since it does not contain other functions, it
is not direclty possible to replace :class:`~numpy.random.RandomState`.
that have changed. Since it does not contain other functions, it
is not directly possible to replace :class:`~numpy.random.RandomState`.
In order to full replace :class:`~numpy.random.RandomState`, it is
necessary to use both :class:`~randomgen.legacy.LegacyGenerator`
and :class:`~randomgen.generator.RandomGenerator` both driven
18 changes: 9 additions & 9 deletions doc/source/reference/random/multithreading.rst
Original file line number Diff line number Diff line change
@@ -21,14 +21,14 @@ seed will produce the same outputs.
import multiprocessing
import concurrent.futures
import numpy as np
class MultithreadedRNG(object):
def __init__(self, n, seed=None, threads=None):
rg = Xoshiro256(seed)
if threads is None:
threads = multiprocessing.cpu_count()
self.threads = threads
self._random_generators = [rg]
last_rg = rg
for _ in range(0, threads-1):
@@ -40,21 +40,21 @@ seed will produce the same outputs.
self.executor = concurrent.futures.ThreadPoolExecutor(threads)
self.values = np.empty(n)
self.step = np.ceil(n / threads).astype(np.int)
def fill(self):
def _fill(random_state, out, first, last):
random_state.standard_normal(out=out[first:last])
futures = {}
for i in range(self.threads):
args = (_fill,
args = (_fill,
self._random_generators[i],
self.values,
i * self.step,
self.values,
i * self.step,
(i + 1) * self.step)
futures[self.executor.submit(*args)] = i
concurrent.futures.wait(futures)
def __del__(self):
self.executor.shutdown(False)
@@ -80,7 +80,7 @@ the time required to generate using a single thread.
In [4]: print(mrng.threads)
...: %timeit mrng.fill()
4
32.8 ms ± 2.71 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
29 changes: 16 additions & 13 deletions doc/source/reference/random/parallel.rst
Original file line number Diff line number Diff line change
@@ -12,20 +12,20 @@ or distributed).
Independent Streams
-------------------

:class:`~threefry.ThreeFry` and :class:`~philox.Philox` support independent
streams. This example shows how many streams can be created by passing in
different index values in the second input while using the same seed in the
first.
:class:`~pcg64.PCG64`, :class:`~threefry.ThreeFry`
and :class:`~philox.Philox` support independent streams. This
example shows how many streams can be created by passing in different index
values in the second input while using the same seed in the first.

.. code-block:: python
from numpy.random.entropy import random_entropy
from numpy.random import ThreeFry
from numpy.random import PCG64
entropy = random_entropy(4)
# 128-bit number as a seed
seed = sum([int(entropy[i]) * 2 ** (32 * i) for i in range(4)])
streams = [ThreeFry(seed, stream) for stream in range(10)]
streams = [PCG64(seed, stream) for stream in range(10)]
:class:`~philox.Philox` and :class:`~threefry.ThreeFry` are
@@ -68,6 +68,8 @@ are listed below.
+-----------------+-------------------------+-------------------------+-------------------------+
| MT19937 | :math:`2^{19937}` | :math:`2^{128}` | 32 |
+-----------------+-------------------------+-------------------------+-------------------------+
| PCG64 | :math:`2^{128}` | :math:`2^{64}` | 64 |
+-----------------+-------------------------+-------------------------+-------------------------+
| Philox | :math:`2^{256}` | :math:`2^{128}` | 64 |
+-----------------+-------------------------+-------------------------+-------------------------+
| ThreeFry | :math:`2^{256}` | :math:`2^{128}` | 64 |
@@ -96,8 +98,9 @@ overlap.
Advance
*******
``advance`` can be used to jump the state an arbitrary number of steps, and so
is a more general approach than ``jumped``. :class:`~threefry.ThreeFry` and
:class:`~philox.Philox` support ``advance``, and since these also support
is a more general approach than ``jumped``. :class:`~pcg64.PCG64`,
:class:`~threefry.ThreeFry` and :class:`~philox.Philox`
support ``advance``, and since these also support
independent streams, it is not usually necessary to use ``advance``.

Advancing a BitGenerator updates the underlying state as-if a given number of
@@ -116,21 +119,21 @@ This occurs for two reasons:
Advancing the BitGenerator state resets any pre-computed random numbers. This
is required to ensure exact reproducibility.

This example uses ``advance`` to advance a :class:`~threefry.ThreeFry`
This example uses ``advance`` to advance a :class:`~pcg64.PCG64`
generator 2 ** 127 steps to set a sequence of random number generators.

.. code-block:: python
from numpy.random import ThreeFry
bit_generator = ThreeFry()
bit_generator_copy = ThreeFry()
from numpy.random import PCG64
bit_generator = PCG64()
bit_generator_copy = PCG64()
bit_generator_copy.state = bit_generator.state
advance = 2**127
bit_generators = [bit_generator]
for _ in range(9):
bit_generator_copy.advance(advance)
bit_generator = ThreeFry()
bit_generator = PCG64()
bit_generator.state = bit_generator_copy.state
bit_generators.append(bit_generator)
38 changes: 21 additions & 17 deletions doc/source/reference/random/performance.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
from collections import OrderedDict
from timeit import repeat

import numpy as np
import pandas as pd

from numpy.random import MT19937, DSFMT, ThreeFry, Philox, Xoshiro256, \
Xoshiro512
import numpy as np
from numpy.random import MT19937, DSFMT, ThreeFry, PCG64, Philox, \
Xoshiro256, Xoshiro512

PRNGS = [DSFMT, MT19937, Philox, ThreeFry, Xoshiro256, Xoshiro512]
PRNGS = [DSFMT, MT19937, PCG64, Philox, ThreeFry, Xoshiro256, Xoshiro512]

funcs = {'32-bit Unsigned Ints': 'integers(0, 2**32,size=1000000, dtype="uint32")',
'64-bit Unsigned Ints': 'integers(0, 2**64,size=1000000, dtype="uint64")',
'Uniforms': 'random(size=1000000)',
'Normals': 'standard_normal(size=1000000)',
'Exponentials': 'standard_exponential(size=1000000)',
'Gammas': 'standard_gamma(3.0,size=1000000)',
'Binomials': 'binomial(9, .1, size=1000000)',
'Laplaces': 'laplace(size=1000000)',
'Poissons': 'poisson(3.0, size=1000000)', }
funcs = OrderedDict()
integers = 'integers(0, 2**{bits},size=1000000, dtype="uint{bits}")'
funcs['32-bit Unsigned Ints'] = integers.format(bits=32)
funcs['64-bit Unsigned Ints'] = integers.format(bits=64)
funcs['Uniforms'] = 'random(size=1000000)'
funcs['Normals'] = 'standard_normal(size=1000000)'
funcs['Exponentials'] = 'standard_exponential(size=1000000)'
funcs['Gammas'] = 'standard_gamma(3.0,size=1000000)'
funcs['Binomials'] = 'binomial(9, .1, size=1000000)'
funcs['Laplaces'] = 'laplace(size=1000000)'
funcs['Poissons'] = 'poisson(3.0, size=1000000)'

setup = """
from numpy.random import {prng}, Generator
@@ -40,7 +42,7 @@
npfuncs = OrderedDict()
npfuncs.update(funcs)
npfuncs['32-bit Unsigned Ints'] = 'randint(2**32,dtype="uint32",size=1000000)'
npfuncs['64-bit Unsigned Ints'] = 'tomaxint(size=1000000)'
npfuncs['64-bit Unsigned Ints'] = 'randint(2**64,dtype="uint64",size=1000000)'
setup = """
from numpy.random import RandomState
rg = RandomState()
@@ -51,18 +53,20 @@
setup.format(prng=prng().__class__.__name__),
number=1, repeat=3)
col[key] = 1000 * min(t)
table['NumPy'] = pd.Series(col)
table['RandomState'] = pd.Series(col)

table = pd.DataFrame(table)
table = table.reindex(table.mean(1).sort_values().index)
order = np.log(table).mean().sort_values().index
table = table.T
table = table.reindex(order)
table = table.T
table = table.reindex([k for k in funcs], axis=0)
print(table.to_csv(float_format='%0.1f'))

rel = table.loc[:, ['NumPy']].values @ np.ones((1, table.shape[1])) / table
rel.pop(rel.columns[0])
rel = table.loc[:, ['RandomState']].values @ np.ones(
(1, table.shape[1])) / table
rel.pop('RandomState')
rel = rel.T
rel['Overall'] = np.exp(np.log(rel).mean(1))
rel *= 100
Loading

0 comments on commit 58c0e72

Please sign in to comment.