Problems with Cython-gil

I have the following code that I am trying to parallelize. Description below

# cython: boundscheck=False
# cython: wraparound=False
# cython: cdivision=True

cimport cython
import numpy as np
cimport numpy as cnp
from numpy cimport ndarray as ar

# define a function pointer
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

    Function
  • stat_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

  1. stat_mat ( range prange):

    range(0, x.shape[0]), prange(x.shape[0], nogil=True)

  2. -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?

+4
2

ctypedef void (*vector_ptr)(double[:], double, double[:])

ctypedef void (*vector_ptr)(double[:], double, double[:]) nogil

.

0
ctypedef void (*vector_ptr)(double[:], double, double[:]) nogil

Baum mit Augen: nogil nogil. nogil prange. nogil, nogil-.

0

All Articles