我有以下代码,我试图并行化。下面的描述的代码Cython - gil相关问题
# 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')
描述以上给出:
功能
sma_vec
,wma_vec
,计算相关数据超过x
和y
返回输出(在该示例中,滚动移动平均和滚动加权移动平均数)。功能
stat_switch
开关要么sma_vec
或wma_vec
取决于的stat_func
和void_vec
的值是一个伪函数什么都不做。函数
stat_vec
返回sma_vec
或wma_vec
输出在1维向量功能
stat_mat
通过循环在2维向量的行(C型的行返回的sma_vec
或wma_vec
输出)功能
stat_choose
检查它是否是1维np.ndarray
维或2维np.ndarray
,并相应地重新导向的结果要么stat_vec
或stat_mat
函数
sma
和wma
旨在用于stat_choose
的python包装。
的安装文件如下:
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
并行化?
我该怎么做? – uday
我的歉意我改变了我的答案。你在做什么对我来说看起来是正确的。我明天可以尝试一些测试。但我已经改变了我的答案在一个非常简单的解决方案,你可能想尝试(但我不能检查,看看它的工作原理)。 –