首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Cython - gil相关问题

Cython - gil相关问题
EN

Stack Overflow用户
提问于 2015-05-23 22:36:09
回答 2查看 1.2K关注 0票数 4

我有下面的代码,我正在尝试并行化。描述如下:

代码语言:javascript
复制
# 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')

上述守则的说明:

  1. 函数sma_vecwma_vec,计算x上的一些度量,并返回y中的输出(在本例中,滚动移动平均和滚动加权移动平均)。
  2. 函数stat_switch根据stat_func的值切换到sma_vecwma_vec,而void_vec是一个什么都不做的虚拟函数。
  3. 函数stat_vec在一维向量上返回sma_vecwma_vec的输出。
  4. 函数stat_mat通过遍历二维向量(C型行)的行返回sma_vecwma_vec的输出。
  5. 函数stat_choose检查它是一维np.ndarray还是二维np.ndarray,并相应地将结果重定向到stat_vecstat_mat
  6. 函数smawma打算成为stat_choose的python。

安装文件如下:

代码语言:javascript
复制
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函数(其中我有一个循环),我执行以下操作:

  1. 在最上面,我补充道:

from cython.parallel import prange

  1. stat_mat代码更改为(将range更改为prange): 我使用的不是range(0, x.shape[0]),而是prange(x.shape[0], nogil=True)
  2. 在安装文件中,我将-fopenmp添加到ext_modulesextra_compile_args=['-O3', '-march=native', '-ffast-math', '-fopenmp'],中。 extra_link_args=['-fopenmp']

当我试图编译它时,我会得到一个错误:

代码语言:javascript
复制
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被并行化?

EN

回答 2

Stack Overflow用户

发布于 2015-05-23 22:59:31

试着改变

代码语言:javascript
复制
ctypedef void (*vector_ptr)(double[:], double, double[:])

代码语言:javascript
复制
ctypedef void (*vector_ptr)(double[:], double, double[:]) nogil

至少我明天才能测试这个。

票数 0
EN

Stack Overflow用户

发布于 2015-05-31 03:01:40

代码语言:javascript
复制
ctypedef void (*vector_ptr)(double[:], double, double[:]) nogil

对于Baum mit Augen:当使用函数指针到nogil函数时,nogil限定符必须是函数指针类型的一部分。只有nogil函数可以在prange块中调用。但是,当函数指针类型不包含nogil限定符时,在橙色或nogil块中调用是非法的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30418238

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档