10000 DOC: Clean up examples of low-level random access by bashtage · Pull Request #14951 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

DOC: Clean up examples of low-level random access #14951

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion numpy/random/_examples/cython/extending.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def uniform_mean(Py_ssize_t n):
return randoms.mean()


# This function is declated nogil so it can be used without the GIL below
# This function is declared nogil so it can be used without the GIL below
cdef uint32_t bounded_uint(uint32_t lb, uint32_t ub, bitgen_t *rng) nogil:
cdef uint32_t mask, delta, val
mask = delta = ub - lb
Expand Down
23 changes: 17 additions & 6 deletions numpy/random/_examples/cython/extending_distributions.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@ import numpy as np
cimport numpy as np
cimport cython
from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer
from libc.stdint cimport uint16_t, uint64_t
from numpy.random._bit_generator cimport bitgen_t

from numpy.random import PCG64


@cython.boundscheck(False)
@cython.wraparound(False)
def uniforms(Py_ssize_t n):
""" Create an array of `n` uniformly distributed doubles.
"""
Create an array of `n` uniformly distributed doubles.
A 'real' distribution would want to process the values into
some non-uniform distribution
"""
Expand All @@ -40,24 +43,32 @@ def uniforms(Py_ssize_t n):
return randoms

# cython example 2

@cython.boundscheck(False)
@cython.wraparound(False)
def uint16_uniforms(Py_ssize_t n):
def uint10_uniforms(Py_ssize_t n):
"""Uniform 10 bit integers stored as 16-bit unsigned integers"""
cdef Py_ssize_t i
cdef bitgen_t *rng
cdef const char *capsule_name = "BitGenerator"
cdef double[::1] random_values
cdef uint16_t[::1] random_values
cdef int bits_remaining
cdef int width = 10
cdef uint64_t buff, mask = 0x3FF

x = PCG64()
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, dtype='uint32')
random_values = np.empty(n, dtype='uint16')
# Best practice is to release GIL and acquire the lock
bits_remaining = 0
with x.lock, nogil:
for i in range(n):
random_values[i] = rng.next_uint32(rng.state)
if bits_remaining < width:
buff = rng.next_uint64(rng.state)
random_values[i] = buff & mask
buff >>= width

randoms = np.asarray(random_values)
return randoms
11 changes: 5 additions & 6 deletions numpy/random/_examples/cython/setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
"""
Build the demos
Build the Cython demonstrations of low-level access to NumPy random

Usage: python setup.py build_ext -i
"""
Expand All @@ -11,18 +11,17 @@
from setuptools.extension import Extension
from os.path import join, abspath, dirname

curpath = abspath(dirname(__file__))
path = abspath(dirname(__file__))

extending = Extension("extending",
sources=[join(curpath, 'extending.pyx')],
sources=[join(path, 'extending.pyx')],
include_dirs=[
np.get_include(),
join(curpath, '..', '..')
join(path, '..', '..')
],
)
distributions = Extension("extending_distributions",
sources=[join(curpath, 'extending_distributions.pyx'),
],
sources=[join(path, 'extending_distributions.pyx')],
include_dirs=[np.get_include()])

extensions = [extending, distributions]
Expand Down
22 changes: 14 additions & 8 deletions numpy/random/_examples/numba/extending_distributions.py
8000
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
r"""
On *nix, execute in randomgen/src/distributions
Building the required library in this example requires a source distribution
of NumPy or clone of the NumPy git repository since distributions.c is not
included in binary distributions.

On *nix, execute in numpy/random/src/distributions

export ${PYTHON_VERSION}=3.8 # Python version
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/
mv libdistributions.so ../../_examples/numba/

On Windows

rem PYTHON_HOME is setup dependent, this is an example
rem PYTHON_HOME and PYTHON_VERSION are setup dependent, this is an example
set PYTHON_HOME=c:\Anaconda
set PYTHON_VERSION=38
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/
-I%PYTHON_HOME%\include %PYTHON_HOME%\libs\python%PYTHON_VERSION%.lib
move distributions.dll ../../_examples/numba/
"""
import os

Expand All @@ -35,19 +41,19 @@
raise RuntimeError('Required DLL/so file was not found.')

ffi.cdef("""
double random_gauss_zig(void *bitgen_state);
double random_standard_normal(void *bitgen_state);
""")
x = PCG64()
xffi = x.cffi
bit_generator = xffi.bit_generator

random_gauss_zig = lib.random_gauss_zig
random_standard_normal = lib.random_standard_normal


def normals(n, bit_generator):
out = np.empty(n)
for i in range(n):
out[i] = random_gauss_zig(bit_generator)
out[i] = random_standard_normal(bit_generator)
return out


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we could run this as part of the tests, like we run the extending.py example

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depends on numba or at least CFFI, so probably not worth it. But definitely a risk that examples get stale, so ideally these things get run somewhere.

Expand Down
0