Я хочу освободить GIL для того, чтобы параллелировать цикл в цитоне, где разные фрагменты памяти просматриваются некоторой функцией внутри цикла. Код выглядит следующим образом:cython memoryviews slices без GIL
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,:])
Это не представляется возможным, так как выбор срез х [D ,:], кажется, требует GIL. Запустив cython -a, и используя обычный цикл, я получаю код, указанный ниже. Как это можно сделать в чистом 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;
Есть примеры 'nogil' в скомпилированном' numpy' и 'scipy' коде. Я предлагаю посмотреть, есть ли в файлах '.pyx'. – hpaulj
numpy/numpy/random/mtrand/mtrand.pyx – hpaulj
Я все еще не понимаю, почему операция вызова среза из memoryview, то есть x [d ,:] требует взаимодействия с python? – tammo