#python #numpy #cython
Вопрос:
Я пытаюсь цитонизировать свой код и удалить как можно больше взаимодействий на python. Я сталкиваюсь с некоторыми проблемами, когда работаю с массивами numpy. У меня есть функция, которая выполняет следующее. Есть некоторые if
else
операторы и циклы for , которые не показывают никаких взаимодействий с python при использовании %%cython --annotate
, и я доволен этим. Однако, несмотря на использование объявления для массива, эти строки кода выделены желтым цветом, указывая на взаимодействие с python.
cdef func(input1, input2):
cdef np.ndarray[np.double_t, ndim=2] array = np.zeros((length, 6))
...
"Some computations"
array[index] = [val1, val2, val3, val4, val5, val6]
"..."
array = array[~np.all(array ==0., axis=1)]
return array
нажав на маленький знак плюс в строке , где написано cdef np.ndarray
, я получаю сообщение об ошибке, показанное ниже, к сожалению, у меня недостаточно опыта, чтобы разобраться в этом.
Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 78, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_2);
__pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_zeros); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 78, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
__pyx_t_2 = __Pyx_PyInt_From_long(__pyx_v_lenpropen); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 78, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_2);
__pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 78, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_4);
__Pyx_GIVEREF(__pyx_t_2);
PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
__Pyx_INCREF(__pyx_int_6);
__Pyx_GIVEREF(__pyx_int_6);
PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_int_6);
__pyx_t_2 = 0;
__pyx_t_2 = NULL;
if (CYTHON_UNPACK_METHODS amp;amp; unlikely(PyMethod_Check(__pyx_t_3))) {
__pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
if (likely(__pyx_t_2)) {
PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
__Pyx_INCREF(__pyx_t_2);
__Pyx_INCREF(function);
__Pyx_DECREF_SET(__pyx_t_3, function);
}
}
__pyx_t_1 = (__pyx_t_2) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_2, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4);
__Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 78, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_1);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 78, __pyx_L1_error)
__pyx_t_5 = ((PyArrayObject *)__pyx_t_1);
{
__Pyx_BufFmt_StackElem __pyx_stack[1];
if (unlikely(__Pyx_GetBufferAndValidate(amp;__pyx_pybuffernd_propen.rcbuffer->pybuffer, (PyObject*)__pyx_t_5, amp;__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {
__pyx_v_propen = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_propen.rcbuffer->pybuffer.buf = NULL;
__PYX_ERR(0, 78, __pyx_L1_error)
} else {__pyx_pybuffernd_propen.diminfo[0].strides = __pyx_pybuffernd_propen.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_propen.diminfo[0].shape = __pyx_pybuffernd_propen.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_propen.diminfo[1].strides = __pyx_pybuffernd_propen.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_propen.diminfo[1].shape = __pyx_pybuffernd_propen.rcbuffer->pybuffer.shape[1];
}
}
__pyx_t_5 = 0;
__pyx_v_propen = ((PyArrayObject *)__pyx_t_1);
__pyx_t_1 = 0;
прочитайте учебник здесь
Я думал, что с помощью декораторов @cython.boundscheck(False)
# Отключить проверку границ
@cython.wraparound(False)
# Деактивировать отрицательную индексацию. может помочь, но это просто не удается скомпилировать полностью
cdef func(input1, input2):
@cython.wraparound(False)
@cython.boundscheck(False)
cdef np.ndarray[np.double_t, ndim=2] array = np.zeros((length, 6))
...
"Some computations"
array[index] = [val1, val2, val3, val4, val5, val6]
"..."
array = array[~np.all(array ==0., axis=1)]
return array
Комментарии:
1. Декораторы выходят за рамки функции (т. е. стандартный синтаксис Python). Они не будут иметь никакого значения для кода, который вы показываете, но они будут компилироваться.
2. @DavidW Ах да. Спасибо! Сейчас он компилируется, другие проблемы все еще остаются в силе. в строках с участием
array
по-прежнему отображаются взаимодействия python в аннотированном коде. Я полагаю, что вы правы, тогда проверка границ не была проблемой.3.
array[index] = [val1, val2, val3, val4, val5, val6]
требуется создать временный объект массива (array[index]
) и назначить список ; и массив , и список являются объектами python. Существует несколько способов избежать создания объектов для этого задания. Один из способов-это сделать:array[index,0] = val1; array[index,1] = val2;
и так далее.4. в Cython, поскольку циклы дешевы и быстры, просто используйте один из них для присвоения ваших значений