From 4aab4087dc97906d0b9890035401175cdaab32d4 Mon Sep 17 00:00:00 2001 From: blackhao <13851610112@163.com> Date: Fri, 22 Aug 2025 02:51:50 -0500 Subject: 2.0 --- .../numba/__pycache__/extending.cpython-312.pyc | Bin 0 -> 3879 bytes .../extending_distributions.cpython-312.pyc | Bin 0 -> 2734 bytes .../numpy/random/_examples/numba/extending.py | 86 +++++++++++++++++++++ .../_examples/numba/extending_distributions.py | 67 ++++++++++++++++ 4 files changed, 153 insertions(+) create mode 100644 .venv/lib/python3.12/site-packages/numpy/random/_examples/numba/__pycache__/extending.cpython-312.pyc create mode 100644 .venv/lib/python3.12/site-packages/numpy/random/_examples/numba/__pycache__/extending_distributions.cpython-312.pyc create mode 100644 .venv/lib/python3.12/site-packages/numpy/random/_examples/numba/extending.py create mode 100644 .venv/lib/python3.12/site-packages/numpy/random/_examples/numba/extending_distributions.py (limited to '.venv/lib/python3.12/site-packages/numpy/random/_examples/numba') diff --git a/.venv/lib/python3.12/site-packages/numpy/random/_examples/numba/__pycache__/extending.cpython-312.pyc b/.venv/lib/python3.12/site-packages/numpy/random/_examples/numba/__pycache__/extending.cpython-312.pyc new file mode 100644 index 0000000..5880d0a Binary files /dev/null and b/.venv/lib/python3.12/site-packages/numpy/random/_examples/numba/__pycache__/extending.cpython-312.pyc differ diff --git a/.venv/lib/python3.12/site-packages/numpy/random/_examples/numba/__pycache__/extending_distributions.cpython-312.pyc b/.venv/lib/python3.12/site-packages/numpy/random/_examples/numba/__pycache__/extending_distributions.cpython-312.pyc new file mode 100644 index 0000000..dc9e447 Binary files /dev/null and b/.venv/lib/python3.12/site-packages/numpy/random/_examples/numba/__pycache__/extending_distributions.cpython-312.pyc differ diff --git a/.venv/lib/python3.12/site-packages/numpy/random/_examples/numba/extending.py b/.venv/lib/python3.12/site-packages/numpy/random/_examples/numba/extending.py new file mode 100644 index 0000000..c1d0f4f --- /dev/null +++ b/.venv/lib/python3.12/site-packages/numpy/random/_examples/numba/extending.py @@ -0,0 +1,86 @@ +from timeit import timeit + +import numba as nb + +import numpy as np +from numpy.random import PCG64 + +bit_gen = PCG64() +next_d = bit_gen.cffi.next_double +state_addr = bit_gen.cffi.state_address + +def normals(n, state): + out = np.empty(n) + for i in range((n + 1) // 2): + x1 = 2.0 * next_d(state) - 1.0 + x2 = 2.0 * next_d(state) - 1.0 + r2 = x1 * x1 + x2 * x2 + while r2 >= 1.0 or r2 == 0.0: + x1 = 2.0 * next_d(state) - 1.0 + x2 = 2.0 * next_d(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 + + +# Compile using Numba +normalsj = nb.jit(normals, nopython=True) +# Must use state address not state with numba +n = 10000 + +def numbacall(): + return normalsj(n, state_addr) + + +rg = np.random.Generator(PCG64()) + +def numpycall(): + return rg.normal(size=n) + + +# Check that the functions work +r1 = numbacall() +r2 = numpycall() +assert r1.shape == (n,) +assert r1.shape == r2.shape + +t1 = timeit(numbacall, number=1000) +print(f'{t1:.2f} secs for {n} PCG64 (Numba/PCG64) gaussian randoms') +t2 = timeit(numpycall, number=1000) +print(f'{t2:.2f} secs for {n} PCG64 (NumPy/PCG64) gaussian randoms') + +# example 2 + +next_u32 = bit_gen.ctypes.next_uint32 +ctypes_state = bit_gen.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 = next_u32(state) & mask + while val > delta: + val = next_u32(state) & mask + + return lb + val + + +print(bounded_uint(323, 2394691, ctypes_state.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, ctypes_state.value) diff --git a/.venv/lib/python3.12/site-packages/numpy/random/_examples/numba/extending_distributions.py b/.venv/lib/python3.12/site-packages/numpy/random/_examples/numba/extending_distributions.py new file mode 100644 index 0000000..d0462e7 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/numpy/random/_examples/numba/extending_distributions.py @@ -0,0 +1,67 @@ +r""" +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/ + +On Windows + +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\python%PYTHON_VERSION%.lib +move distributions.dll ../../_examples/numba/ +""" +import os + +import numba as nb +from cffi import FFI + +import numpy as np +from numpy.random import PCG64 + +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_standard_normal(void *bitgen_state); +""") +x = PCG64() +xffi = x.cffi +bit_generator = xffi.bit_generator + +random_standard_normal = lib.random_standard_normal + + +def normals(n, bit_generator): + out = np.empty(n) + for i in range(n): + out[i] = random_standard_normal(bit_generator) + return out + + +normalsj = nb.jit(normals, nopython=True) + +# Numba requires a memory address for void * +# Can also get address from x.ctypes.bit_generator.value +bit_generator_address = int(ffi.cast('uintptr_t', bit_generator)) + +norm = normalsj(1000, bit_generator_address) +print(norm[:12]) -- cgit v1.2.3