I have the following code that I am trying to parallelize. Description below
cimport cython
import numpy as np
cimport numpy as cnp
from numpy cimport ndarray as ar
ctypedef void (*vector_ptr)(double[:], double, double[:])
cdef void sma_vec(double[:] x, double m, double[:] y) nogil:
cdef:
int n
int mi = int(m)
Py_ssize_t i, j
n = x.shape[0]
for i in range(mi-1, n):
for j in range(i-mi+1, i+1):
if j == i-mi+1:
y[i] = x[j]
else:
y[i] += x[j]
y[i] /= m
cdef void wma_vec(double[:] x, double m, double[:] y) nogil:
cdef:
int n
int mi = int(m)
Py_ssize_t i, j
n = x.shape[0]
for i in range(mi-1, n):
for j in range(i-mi+1, i+1):
if j == i-mi+1:
y[i] = x[j]
else:
y[i] += x[j]*float(j-i+m)
y[i] /= float(m*(m+1))/2.0
cdef void void_vec(double[:] x, double m, double[:] y) nogil:
pass
cdef vector_ptr stat_switch(stat_func):
if stat_func == 'sma':
return &sma_vec
elif stat_func == 'wma':
return &wma_vec
else:
return &void_vec
cdef double[:] stat_vec(double[:] x, double m, stat_func):
cdef:
vector_ptr stat_func_ptr = stat_switch(stat_func)
double[:] y = x.copy()
y[:] = np.nan
stat_func_ptr(x, m, y)
return y
cdef double[:, ::1] stat_mat(double[:, ::1] x, double m, stat_func):
cdef:
vector_ptr stat_func_ptr = stat_switch(stat_func)
int n
Py_ssize_t i
double[:, ::1] y = x.copy()
double[:] yi
double[:] xi
y[:, :] = np.nan
n = x.shape[1]
if n > int(m):
for i in range(0, x.shape[0]):
yi = y[i, :]
xi = x[i, :]
stat_func_ptr(xi, m, yi)
return y
cdef ar stat_choose(ar x, double m, stat_func):
if x.ndim == 1:
return np.asarray(stat_vec(x, m, stat_func))
elif x.ndim == 2:
return np.asarray(stat_mat(x, m, stat_func))
else:
raise ValueError('Cannot handle more than two dimensions')
cpdef ar sma(ar x, double m):
return stat_choose(x, m, 'sma')
cpdef ar wma(ar x, double m):
return stat_choose(x, m, 'wma')
Description of the above code:
function sma_vec, wma_veccalculate some metric over xand return the result y(in this example, the sliding moving average and moving weighted moving average).
The function stat_switchswitches to sma_vecor wma_vecdepending on the value stat_funcand void_vecis a dummy function that does nothing.
The function stat_vecreturns a result sma_vecor wma_vecover a 1-dimensional vector
Functionstat_matreturns the result sma_veceither wma_vecby cyclic moving through the lines of a two-dimensional vector (C-type lines)
stat_choose , 1- np.ndarray 2- np.ndarray stat_vec stat_mat
sma wma python stat_choose.
:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
import numpy as np
ext_modules = [Extension('movavg1', ['stat/movavg1.pyx'], include_dirs=[np.get_include()],
define_macros=[('NPY_NO_DEPRECATED_API', None)],
extra_compile_args=['-O3', '-march=native', '-ffast-math']
)]
setup(
name="Moving Average Functions",
cmdclass={'build_ext': build_ext},
ext_modules=ext_modules
)
stat_mat, , :
from cython.parallel import prange
stat_mat ( range prange):
range(0, x.shape[0]), prange(x.shape[0], nogil=True)
-fopenmp ext_modules:
extra_compile_args=['-O3', '-march=native', '-ffast-math', '-fopenmp'],
extra_link_args=['-fopenmp']
, :
Error compiling Cython file:
------------------------------------------------------------
...
n = x.shape[1]
if n > int(m):
for i in prange(x.shape[0], nogil=True):
yi = y[i, :]
xi = x[i, :]
stat_func_ptr(xi, m, yi)
^
------------------------------------------------------------
stat\movavg1.pyx:73:25: Calling gil-requiring function not allowed
without gil
, stat_mat?