summaryrefslogtreecommitdiff
path: root/numpy/random/examples/numba
diff options
context:
space:
mode:
authormattip <matti.picus@gmail.com>2019-04-10 00:50:42 +0300
committermattip <matti.picus@gmail.com>2019-05-20 18:45:27 +0300
commitc53b2eb729bae1f248a2654dfcfa4a3dd3e2902b (patch)
treeeed1d982201dc892984feaca355565217069eb20 /numpy/random/examples/numba
parent7e8e19f9a3b452fdbd992568348b393c31fba005 (diff)
downloadnumpy-c53b2eb729bae1f248a2654dfcfa4a3dd3e2902b.tar.gz
BENCH: convert bencmarks to asv format
remove files that were part of the origal repo rework randomgen docs to integrate with numpy and fix some links remove convenience functions, require explicit call to gen.brng move code out of numpy.random.randomgen into numpy.random
Diffstat (limited to 'numpy/random/examples/numba')
-rw-r--r--numpy/random/examples/numba/extending.py77
-rw-r--r--numpy/random/examples/numba/extending_distributions.py60
2 files changed, 137 insertions, 0 deletions
diff --git a/numpy/random/examples/numba/extending.py b/numpy/random/examples/numba/extending.py
new file mode 100644
index 000000000..72e903b1f
--- /dev/null
+++ b/numpy/random/examples/numba/extending.py
@@ -0,0 +1,77 @@
+import datetime as dt
+
+import numpy as np
+import numba as nb
+
+from randomgen import Xoroshiro128
+
+x = Xoroshiro128()
+f = x.ctypes.next_uint32
+s = x.ctypes.state
+
+
+@nb.jit(nopython=True)
+def bounded_uint(lb, ub, state):
+ mask = delta = ub - lb
+ mask |= mask >> 1
+ mask |= mask >> 2
+ mask |= mask >> 4
+ mask |= mask >> 8
+ mask |= mask >> 16
+
+ val = f(state) & mask
+ while val > delta:
+ val = f(state) & mask
+
+ return lb + val
+
+
+print(bounded_uint(323, 2394691, s.value))
+
+
+@nb.jit(nopython=True)
+def bounded_uints(lb, ub, n, state):
+ out = np.empty(n, dtype=np.uint32)
+ for i in range(n):
+ out[i] = bounded_uint(lb, ub, state)
+
+
+bounded_uints(323, 2394691, 10000000, s.value)
+
+g = x.cffi.next_double
+cffi_state = x.cffi.state
+state_addr = x.cffi.state_address
+
+
+def normals(n, state):
+ out = np.empty(n)
+ for i in range((n + 1) // 2):
+ x1 = 2.0 * g(state) - 1.0
+ x2 = 2.0 * g(state) - 1.0
+ r2 = x1 * x1 + x2 * x2
+ while r2 >= 1.0 or r2 == 0.0:
+ x1 = 2.0 * g(state) - 1.0
+ x2 = 2.0 * g(state) - 1.0
+ r2 = x1 * x1 + x2 * x2
+ f = np.sqrt(-2.0 * np.log(r2) / r2)
+ out[2 * i] = f * x1
+ if 2 * i + 1 < n:
+ out[2 * i + 1] = f * x2
+ return out
+
+
+print(normals(10, cffi_state).var())
+# Warm up
+normalsj = nb.jit(normals, nopython=True)
+normalsj(1, state_addr)
+
+start = dt.datetime.now()
+normalsj(1000000, state_addr)
+ms = 1000 * (dt.datetime.now() - start).total_seconds()
+print('1,000,000 Polar-transform (numba/Xoroshiro128) randoms in '
+ '{ms:0.1f}ms'.format(ms=ms))
+
+start = dt.datetime.now()
+np.random.standard_normal(1000000)
+ms = 1000 * (dt.datetime.now() - start).total_seconds()
+print('1,000,000 Polar-transform (NumPy) randoms in {ms:0.1f}ms'.format(ms=ms))
diff --git a/numpy/random/examples/numba/extending_distributions.py b/numpy/random/examples/numba/extending_distributions.py
new file mode 100644
index 000000000..17ba2704c
--- /dev/null
+++ b/numpy/random/examples/numba/extending_distributions.py
@@ -0,0 +1,60 @@
+r"""
+On *nix, execute in randomgen/src/distributions
+
+export PYTHON_INCLUDE=#path to Python's include folder, usually \
+ ${PYTHON_HOME}/include/python${PYTHON_VERSION}m
+export NUMPY_INCLUDE=#path to numpy's include folder, usually \
+ ${PYTHON_HOME}/lib/python${PYTHON_VERSION}/site-packages/numpy/core/include
+gcc -shared -o libdistributions.so -fPIC distributions.c -I${NUMPY_INCLUDE} \
+ -I${PYTHON_INCLUDE}
+mv libdistributions.so ../../examples/numba/
+
+On Windows
+
+rem PYTHON_HOME is setup dependent, this is an example
+set PYTHON_HOME=c:\Anaconda
+cl.exe /LD .\distributions.c -DDLL_EXPORT \
+ -I%PYTHON_HOME%\lib\site-packages\numpy\core\include \
+ -I%PYTHON_HOME%\include %PYTHON_HOME%\libs\python36.lib
+move distributions.dll ../../examples/numba/
+"""
+import os
+
+import numba as nb
+import numpy as np
+from cffi import FFI
+
+from randomgen import Xoroshiro128
+
+ffi = FFI()
+if os.path.exists('./distributions.dll'):
+ lib = ffi.dlopen('./distributions.dll')
+elif os.path.exists('./libdistributions.so'):
+ lib = ffi.dlopen('./libdistributions.so')
+else:
+ raise RuntimeError('Required DLL/so file was not found.')
+
+ffi.cdef("""
+double random_gauss_zig(void *brng_state);
+""")
+x = Xoroshiro128()
+xffi = x.cffi
+brng = xffi.brng
+
+random_gauss_zig = lib.random_gauss_zig
+
+
+def normals(n, brng):
+ out = np.empty(n)
+ for i in range(n):
+ out[i] = random_gauss_zig(brng)
+ return out
+
+
+normalsj = nb.jit(normals, nopython=True)
+
+# Numba requires a memory address for void *
+# Can also get address from x.ctypes.brng.value
+brng_address = int(ffi.cast('uintptr_t', brng))
+
+norm = normalsj(1000, brng_address)