summaryrefslogtreecommitdiff
path: root/doc/source/reference
diff options
context:
space:
mode:
authorKevin Sheppard <kevin.k.sheppard@gmail.com>2019-05-23 15:28:22 +0100
committermattip <matti.picus@gmail.com>2019-05-27 22:58:35 +0300
commitdabf42be29208a59bbacffd40d9d8dca6e200f49 (patch)
tree929ddc66702b257a8ffa372939d38bb42c041414 /doc/source/reference
parent7c52c2810e20a9e483e564751b8e2342c97f56c2 (diff)
downloadnumpy-dabf42be29208a59bbacffd40d9d8dca6e200f49.tar.gz
MAINT: Remove remnants of bit generators
Remove traces of the three removed bit generators Add lock to Cython examples
Diffstat (limited to 'doc/source/reference')
-rw-r--r--doc/source/reference/random/extending.rst95
-rw-r--r--doc/source/reference/random/generator.rst2
-rw-r--r--doc/source/reference/random/multithreading.rst12
-rw-r--r--doc/source/reference/random/parallel.rst8
-rw-r--r--doc/source/reference/random/performance.py7
-rw-r--r--doc/source/reference/random/performance.rst67
6 files changed, 93 insertions, 98 deletions
diff --git a/doc/source/reference/random/extending.rst b/doc/source/reference/random/extending.rst
index f65d7708f..28db4021c 100644
--- a/doc/source/reference/random/extending.rst
+++ b/doc/source/reference/random/extending.rst
@@ -18,11 +18,11 @@ provided by ``ctypes.next_double``.
.. code-block:: python
- from numpy.random import Xoroshiro128
+ from numpy.random import Xoshiro256
import numpy as np
import numba as nb
- x = Xoroshiro128()
+ x = Xoshiro256()
f = x.ctypes.next_double
s = x.ctypes.state
state_addr = x.ctypes.state_address
@@ -50,7 +50,7 @@ provided by ``ctypes.next_double``.
# Must use state address not state with numba
normalsj(1, state_addr)
%timeit normalsj(1000000, state_addr)
- print('1,000,000 Box-Muller (numba/Xoroshiro128) randoms')
+ print('1,000,000 Box-Muller (numba/Xoshiro256) randoms')
%timeit np.random.standard_normal(1000000)
print('1,000,000 Box-Muller (NumPy) randoms')
@@ -66,7 +66,7 @@ Cython
======
Cython can be used to unpack the ``PyCapsule`` provided by a BitGenerator.
-This example uses `~xoroshiro128.Xoroshiro128` and
+This example uses `~xoshiro256.Xoshiro256` and
``random_gauss_zig``, the Ziggurat-based generator for normals, to fill an
array. The usual caveats for writing high-performance code using Cython --
removing bounds checks and wrap around, providing array alignment information
@@ -80,54 +80,57 @@ removing bounds checks and wrap around, providing array alignment information
from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer
from numpy.random.common cimport *
from numpy.random.distributions cimport random_gauss_zig
- from numpy.random import Xoroshiro128
-
-
- @cython.boundscheck(False)
- @cython.wraparound(False)
- def normals_zig(Py_ssize_t n):
- cdef Py_ssize_t i
- cdef bitgen_t *rng
- cdef const char *capsule_name = "BitGenerator"
- cdef double[::1] random_values
-
- x = Xoroshiro128()
- capsule = x.capsule
- if not PyCapsule_IsValid(capsule, capsule_name):
- raise ValueError("Invalid pointer to anon_func_state")
- rng = <bitgen_t *> PyCapsule_GetPointer(capsule, capsule_name)
- random_values = np.empty(n)
- for i in range(n):
- random_values[i] = random_gauss_zig(rng)
- randoms = np.asarray(random_values)
- return randoms
+ from numpy.random import Xoshiro256
+
+
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ def normals_zig(Py_ssize_t n):
+ cdef Py_ssize_t i
+ cdef bitgen_t *rng
+ cdef const char *capsule_name = "BitGenerator"
+ cdef double[::1] random_values
+
+ x = Xoshiro256()
+ capsule = x.capsule
+ if not PyCapsule_IsValid(capsule, capsule_name):
+ raise ValueError("Invalid pointer to anon_func_state")
+ rng = <bitgen_t *> PyCapsule_GetPointer(capsule, capsule_name)
+ random_values = np.empty(n)
+ # Best practice is to release GIL and acquire the lock
+ with x.lock, nogil:
+ for i in range(n):
+ random_values[i] = random_gauss_zig(rng)
+ randoms = np.asarray(random_values)
+ return randoms
The BitGenerator can also be directly accessed using the members of the basic
RNG structure.
.. code-block:: cython
- @cython.boundscheck(False)
- @cython.wraparound(False)
- def uniforms(Py_ssize_t n):
- cdef Py_ssize_t i
- cdef bitgen_t *rng
- cdef const char *capsule_name = "BitGenerator"
- cdef double[::1] random_values
-
- x = Xoroshiro128()
- capsule = x.capsule
- # Optional check that the capsule if from a Basic RNG
- if not PyCapsule_IsValid(capsule, capsule_name):
- raise ValueError("Invalid pointer to anon_func_state")
- # Cast the pointer
- rng = <bitgen_t *> PyCapsule_GetPointer(capsule, capsule_name)
- random_values = np.empty(n)
- for i in range(n):
- # Call the function
- random_values[i] = rng.next_double(rng.state)
- randoms = np.asarray(random_values)
- return randoms
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ def uniforms(Py_ssize_t n):
+ cdef Py_ssize_t i
+ cdef bitgen_t *rng
+ cdef const char *capsule_name = "BitGenerator"
+ cdef double[::1] random_values
+
+ x = Xoshiro256()
+ capsule = x.capsule
+ # Optional check that the capsule if from a BitGenerator
+ if not PyCapsule_IsValid(capsule, capsule_name):
+ raise ValueError("Invalid pointer to anon_func_state")
+ # Cast the pointer
+ rng = <bitgen_t *> PyCapsule_GetPointer(capsule, capsule_name)
+ random_values = np.empty(n)
+ with x.lock, nogil:
+ for i in range(n):
+ # Call the function
+ random_values[i] = rng.next_double(rng.state)
+ randoms = np.asarray(random_values)
+ return randoms
These functions along with a minimal setup file are included in the
examples folder.
diff --git a/doc/source/reference/random/generator.rst b/doc/source/reference/random/generator.rst
index ee70725e7..8b086e901 100644
--- a/doc/source/reference/random/generator.rst
+++ b/doc/source/reference/random/generator.rst
@@ -8,7 +8,7 @@ a wide range of distributions, and served as a replacement for
the two is that ``Generator`` relies on an additional BitGenerator to
manage state and generate the random bits, which are then transformed into
random values from useful distributions. The default BitGenerator used by
-``Generator`` is :class:`~xoroshiro128.Xoroshiro128`. The BitGenerator
+``Generator`` is :class:`~xoshiro256.Xoshiro256`. The BitGenerator
can be changed by passing an instantized BitGenerator to ``Generator``.
diff --git a/doc/source/reference/random/multithreading.rst b/doc/source/reference/random/multithreading.rst
index 718fe05f1..871425e6d 100644
--- a/doc/source/reference/random/multithreading.rst
+++ b/doc/source/reference/random/multithreading.rst
@@ -10,21 +10,21 @@ these requirements.
This example makes use of Python 3 :mod:`concurrent.futures` to fill an array
using multiple threads. Threads are long-lived so that repeated calls do not
require any additional overheads from thread creation. The underlying
-BitGenerator is `Xorshift1024` which is fast, has a long period and supports
-using `Xorshift1024.jumped` to return a new generator while advancing the
+BitGenerator is `Xoshiro256` which is fast, has a long period and supports
+using `Xoshiro256.jumped` to return a new generator while advancing the
state. The random numbers generated are reproducible in the sense that the same
seed will produce the same outputs.
.. code-block:: ipython
- from numpy.random import Generator, Xorshift1024
+ from numpy.random import Generator, Xoshiro256
import multiprocessing
import concurrent.futures
import numpy as np
class MultithreadedRNG(object):
def __init__(self, n, seed=None, threads=None):
- rg = Xorshift1024(seed)
+ rg = Xoshiro256(seed)
if threads is None:
threads = multiprocessing.cpu_count()
self.threads = threads
@@ -89,7 +89,7 @@ The single threaded call directly uses the BitGenerator.
.. code-block:: ipython
In [5]: values = np.empty(10000000)
- ...: rg = Generator(Xorshift1024())
+ ...: rg = Generator(Xoshiro256())
...: %timeit rg.standard_normal(out=values)
99.6 ms ± 222 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
@@ -100,7 +100,7 @@ that does not use an existing array due to array creation overhead.
.. code-block:: ipython
- In [6]: rg = Generator(Xorshift1024())
+ In [6]: rg = Generator(Xoshiro256())
...: %timeit rg.standard_normal(10000000)
125 ms ± 309 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
diff --git a/doc/source/reference/random/parallel.rst b/doc/source/reference/random/parallel.rst
index 8bdc3f23f..40f0bce63 100644
--- a/doc/source/reference/random/parallel.rst
+++ b/doc/source/reference/random/parallel.rst
@@ -72,10 +72,6 @@ are listed below.
+-----------------+-------------------------+-------------------------+-------------------------+
| ThreeFry | :math:`2^{256}` | :math:`2^{128}` | 64 |
+-----------------+-------------------------+-------------------------+-------------------------+
-| Xoroshiro128 | :math:`2^{128}` | :math:`2^{64}` | 64 |
-+-----------------+-------------------------+-------------------------+-------------------------+
-| Xorshift1024 | :math:`2^{1024}` | :math:`2^{512}` | 64 |
-+-----------------+-------------------------+-------------------------+-------------------------+
| Xoshiro256** | :math:`2^{256}` | :math:`2^{128}` | 64 |
+-----------------+-------------------------+-------------------------+-------------------------+
| Xoshiro512** | :math:`2^{512}` | :math:`2^{256}` | 64 |
@@ -87,13 +83,13 @@ overlap.
.. code-block:: python
from numpy.random.entropy import random_entropy
- from numpy.random import Xorshift1024
+ from numpy.random import Xoshiro256
entropy = random_entropy(2).astype(np.uint64)
# 64-bit number as a seed
seed = entropy[0] * 2**32 + entropy[1]
blocked_rng = []
- rng = Xorshift1024(seed)
+ rng = Xoshiro256(seed)
for i in range(10):
blocked_rng.append(rng.jumped(i))
diff --git a/doc/source/reference/random/performance.py b/doc/source/reference/random/performance.py
index a29e09c41..bbf17b1d0 100644
--- a/doc/source/reference/random/performance.py
+++ b/doc/source/reference/random/performance.py
@@ -4,11 +4,10 @@ from timeit import repeat
import numpy as np
import pandas as pd
-from numpy.random import MT19937, DSFMT, ThreeFry, Xoroshiro128, \
- Xorshift1024, Philox, Xoshiro256, Xoshiro512
+from numpy.random import MT19937, DSFMT, ThreeFry, Philox, Xoshiro256, \
+ Xoshiro512
-PRNGS = [DSFMT, MT19937, Philox, ThreeFry, Xoroshiro128, Xorshift1024,
- Xoshiro256, Xoshiro512]
+PRNGS = [DSFMT, MT19937, 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")',
diff --git a/doc/source/reference/random/performance.rst b/doc/source/reference/random/performance.rst
index 61898ac89..395744eb8 100644
--- a/doc/source/reference/random/performance.rst
+++ b/doc/source/reference/random/performance.rst
@@ -8,25 +8,22 @@ Performance
Recommendation
**************
The recommended generator for single use is
-:class:`~xoroshiro128.Xoroshiro128`. The recommended generator
+:class:`~.xoshiro256.Xoshiro256`. The recommended generator
for use in large-scale parallel applications is
-:class:`~.xoshiro256.Xoshiro256`
-where the `jumped` method is used to advance the state. For very large scale
-applications -- requiring 1,000+ independent streams,
-:class:`~.philox.Philox` is the best choice.
+:class:`~.xoshiro512.Xoshiro512` where the `jumped` method is used to advance
+the state. For very large scale applications -- requiring 1,000+ independent
+streams -- :class:`~.philox.Philox` is the best choice.
Timings
*******
The timings below are the time in ns to produce 1 random value from a
-specific distribution. :class:`~xoroshiro128.Xoroshiro128` is the
-fastest, followed by :class:`~xorshift1024.Xorshift1024`. The original
-:class:`~mt19937.MT19937` generator is much slower since it requires 2 32-bit
-values to equal the output of the faster generators.
+specific distribution. The original :class:`~mt19937.MT19937` generator is
+much slower since it requires 2 32-bit values to equal the output of the
+faster generators.
Integer performance has a similar ordering although `dSFMT` is slower since
-it generates 53-bit floating point values rather than integer values. On the
-other hand, it is very fast for uniforms, although slower than `xoroshiro128+`.
+it generates 53-bit floating point values rather than integer values.
The pattern is similar for other, more complex generators. The normal
performance of NumPy's MT19937 is much lower than the other since it
@@ -35,38 +32,38 @@ performance gap for Exponentials is also large due to the cost of computing
the log function to invert the CDF.
.. csv-table::
- :header: ,Xoroshiro128,Xoshiro256**,Xorshift1024,MT19937,Philox,ThreeFry,NumPy
+ :header: ,Xoshiro256**,Xoshiro512**,DSFMT,MT19937,Philox,NumPy,ThreeFry
:widths: 14,14,14,14,14,14,14,14
- 64-bit Unsigned Ints,11.9,13.6,14.9,18.0,22.0,25.9,42.0
- Uniforms,16.3,15.6,16.0,19.1,23.5,25.5,44.1
- 32-bit Unsigned Ints,21.6,23.7,23.1,23.6,27.9,32.3,17.9
- Exponentials,21.2,22.4,23.8,26.7,30.8,33.0,115.3
- Normals,25.1,26.9,26.2,31.7,32.6,37.8,106.8
- Binomials,72.4,73.0,71.9,77.4,80.0,83.1,101.9
- Complex Normals,80.4,86.4,81.1,93.4,96.3,105.5,
- Laplaces,97.0,97.4,99.6,109.8,102.3,105.1,125.3
- Gammas,91.3,91.2,94.8,101.7,108.7,113.8,187.9
- Poissons,136.7,137.6,139.7,161.9,171.0,181.0,265.1
+ 32-bit Unsigned Ints,2.6,2.9,3.4,3.2,5.0,3.3,7.6
+ 64-bit Unsigned Ints,3.1,4.0,5.6,5.7,6.6,8.1,13.4
+ Uniforms,3.7,4.2,3.2,7.4,9.1,8.9,13.5
+ Exponentials,4.3,5.3,7.3,8.2,9.7,42.4,14.9
+ Normals,8.2,8.9,11.7,13.4,15.0,37.3,18.6
+ Binomials,20.0,20.8,19.8,26.4,28.2,26.6,31.0
+ Gammas,26.4,28.7,30.4,37.1,38.8,62.9,49.0
+ Laplaces,40.2,40.0,39.4,48.7,51.2,47.4,51.4
+ Poissons,48.8,51.6,47.8,73.6,82.3,74.0,90.6
-The next table presents the performance relative to `xoroshiro128+` in
-percentage. The overall performance was computed using a geometric mean.
+The next table presents the performance in percentage relative to values
+generated by the legagy generator, `RandomState(MT19937())`. The overall
+performance was computed using a geometric mean.
.. csv-table::
- :header: ,Xoroshiro128,Xoshiro256**,Xorshift1024,MT19937,Philox,ThreeFry
+ :header: ,Xoshiro256**,Xoshiro512**,DSFMT,MT19937,Philox,ThreeFry
:widths: 14,14,14,14,14,14,14
- 64-bit Unsigned Ints,353,309,283,233,191,162
- Uniforms,271,283,276,232,188,173
- 32-bit Unsigned Ints,83,76,78,76,64,56
- Exponentials,544,514,485,432,375,350
- Normals,425,397,407,337,328,283
- Binomials,141,140,142,132,127,123
- Laplaces,129,129,126,114,123,119
- Gammas,206,206,198,185,173,165
- Poissons,194,193,190,164,155,146
- Overall,223,215,210,186,170,156
+ 32-bit Unsigned Ints,129,113,98,103,66,44
+ 64-bit Unsigned Ints,258,202,145,142,122,61
+ Uniforms,244,214,283,121,98,66
+ Exponentials,981,796,580,518,436,285
+ Normals,453,417,319,278,249,200
+ Binomials,133,128,134,101,94,86
+ Gammas,238,219,207,170,162,129
+ Laplaces,118,118,120,97,93,92
+ Poissons,152,144,155,101,90,82
+ Overall,233,209,194,152,130,98
.. note::