cython prange - 处理__Pyx_ErrFetchWithState / __Pyx_ErrRestoreWithState

时间:2017-06-21 12:19:04

标签: python multithreading cython

我正在使用prange来修改数组。我尝试在cython编译器生成的HTML页面中尽可能少的黄线:

cython function_prange.pyx -a

但是当提取数组的一部分来修改它时,我总是会生成这样的代码:

{
    #ifdef WITH_THREAD
    PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();
    #endif
    #ifdef _OPENMP
    #pragma omp flush(__pyx_parallel_exc_type)
    #endif /* _OPENMP */
    if (!__pyx_parallel_exc_type) {
      __Pyx_ErrFetchWithState(&__pyx_parallel_exc_type, &__pyx_parallel_exc_value, &__pyx_parallel_exc_tb);
      __pyx_parallel_filename = __pyx_filename; __pyx_parallel_lineno = __pyx_lineno; __pyx_parallel_clineno = __pyx_clineno;
      __Pyx_GOTREF(__pyx_parallel_exc_type);
    }
    #ifdef WITH_THREAD
    PyGILState_Release(__pyx_gilstate_save);
    #endif
}

是否可以避免这些__Pyx_ErrFetchWithState / __Pyx_ErrRestoreWithState?这真的很重要吗?

以下是我正在使用的代码:

第一个函数在 function_nogil.pyx

中向一个大小为1的数组中的矩阵的对角线添加一个double
import cython

@cython.boundscheck(False) # turn off bounds-checking for entire function
@cython.wraparound(False)  # turn off negative index wrapping for entire function
cdef void add_diag(double [:,:,:] a, int a_len, int a_wid, double coeff) nogil:
    cdef int x_max = a_len

    cdef int x
    for x in xrange(x_max):
        a[0,x,x] = a[0,x,x] + coeff

function_nogil.pxd

中的标题
cdef void add_diag(double [:,:,:] a, int a_len, int a_wid, double coeff) nogil

function_prange.pyx中使用prange的功能

@cython.boundscheck(False) # turn off bounds-checking for entire function
@cython.wraparound(False)  # turn off negative index wrapping for entire function
def prange_loop_idx(double [:,:,:] a, int a_dim1, int a_dim2, int a_dim3, double coeff,int num_threads):

    cdef int i = 0

    with nogil,parallel(num_threads=num_threads):
        for i in prange(a_dim1):
            add_diag(a[i:i+1:,],a_dim2,a_dim3,coeff)

1 个答案:

答案 0 :(得分:1)

它没有它看起来那么糟糕。当你查看完整的C代码时,你会发现这只是一个错误处理代码,只有在出现错误情况后才能通过powershell.exe -file "stuff.ps1" "ValueforParam1" "ValueForParam2" 跳转到它来执行。

(错误条件是它检查memoryview切片是否构造正确 - 我认为这是使用切片而不是单个索引的结果。将步骤设置为0会在此处触发错误。)< / p>

所以你有一些额外的错误检查可能并非严格必要,但我认为单独留下是明智的(在我的电脑上就是这条线):

goto

但你担心的实际代码在正常操作中没有被调用,因此几乎没有成本,你可以忽略。

我认为if (unlikely(__pyx_memoryview_slice_memviewslice( &__pyx_t_4, __pyx_v_a.shape[0], __pyx_v_a.strides[0], __pyx_v_a.suboffsets[0], 0, 0, &__pyx_t_5, __pyx_v_i, (__pyx_v_i + 1), 0, 1, 1, 0, 1) < 0)) { __PYX_ERR(0, 21, __pyx_L12_error) } parallel生成的代码可能足够复杂,以至于生成的html文件在向您显示正确位时并非100%有用,这就是您看到的原因它链接到该行,但您没有看到我上面显示的错误检查代码。