【问题标题】:cython memoryviews slices without GIL没有 GIL 的 cython memoryviews 切片
【发布时间】:2016-10-24 16:04:15
【问题描述】:

我想释放 GIL 以并行化 cython 中的循环,其中不同的内存视图切片被传递给循环内的某个函数。代码如下所示:

cpdef void do_sth_in_parallel(bint[:,:] input, bint[:] output, int D):
     for d in prange(D, schedule=dynamic, nogil=True):
          ouput[d] = some_function_not_requiring_gil(x[d,:])

这是不可能的,因为选择切片 x[d,:] 似乎需要 GIL。运行 cython -a,并使用普通的 for 循环,我得到了下面发布的代码。这如何在纯 C 中完成?

      __pyx_t_5.data = __pyx_v_x.data;
      __pyx_t_5.memview = __pyx_v_x.memview;
      __PYX_INC_MEMVIEW(&__pyx_t_5, 0);
      {
    Py_ssize_t __pyx_tmp_idx = __pyx_v_d;
    Py_ssize_t __pyx_tmp_shape = __pyx_v_x.shape[0];
    Py_ssize_t __pyx_tmp_stride = __pyx_v_x.strides[0];
    if (0 && (__pyx_tmp_idx < 0))
        __pyx_tmp_idx += __pyx_tmp_shape;
    if (0 && (__pyx_tmp_idx < 0 || __pyx_tmp_idx >= __pyx_tmp_shape)) {
        PyErr_SetString(PyExc_IndexError, "Index out of bounds (axis 0)");
        __PYX_ERR(0, 130, __pyx_L1_error)
    }
        __pyx_t_5.data += __pyx_tmp_idx * __pyx_tmp_stride;
}

__pyx_t_5.shape[0] = __pyx_v_x.shape[1];
__pyx_t_5.strides[0] = __pyx_v_x.strides[1];
    __pyx_t_5.suboffsets[0] = -1;

__pyx_t_6.data = __pyx_v_u.data;
      __pyx_t_6.memview = __pyx_v_u.memview;
      __PYX_INC_MEMVIEW(&__pyx_t_6, 0);
      __pyx_t_6.shape[0] = __pyx_v_u.shape[0];
__pyx_t_6.strides[0] = __pyx_v_u.strides[0];
    __pyx_t_6.suboffsets[0] = -1;

【问题讨论】:

  • 在编译的numpyscipy代码中有nogil的例子。我建议查看.pyx 文件中是否有任何内容。
  • numpy/numpy/random/mtrand/mtrand.pyx
  • 还是看不懂为什么从memoryview调用切片的操作,即x[d,:]需要python交互?

标签: parallel-processing cython gil


【解决方案1】:

以下对我有用:

from cython.parallel import prange

cdef bint some_function_not_requiring_gil(bint[:] x) nogil:
    return x[0]

cpdef void do_sth_in_parallel(bint[:,:] input, bint[:] output, int D):
     cdef int d
     for d in prange(D, schedule=dynamic, nogil=True):
          output[d] = some_function_not_requiring_gil(input[d,:])

我必须做的两个主要更改是 xinput(因为它假设它可以在全局范围内找到 x 作为 python 对象)来修复错误

在没有 gil 的情况下不允许转换为 Python 对象

并添加cdef int d以强制d的类型并修复错误

没有 GIL 就不允许来自 Python 的强制

(我还创建了一个示例some_function_not_requiring_gil,但我认为这很明显)

【讨论】:

    【解决方案2】:

    适合我的解决方案:

    使用访问数组切片

    input[d:d+1, :]
    

    而不是

    input [d,:]
    

    并传递一个二维数组。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多