#python #python-2.7 #optimization #cython
#python #python-2.7 #оптимизация #cython
Вопрос:
Я пишу на cython (python 2.7) и имею дело с циклами «для». Пока я использую стандарт for i in range(N)
, я получил классный код: нет желтого предупреждения на cythonized code.html
.
Когда я создаю список целых чисел (как range (N), не так ли?), Например:
cdef long [:] lista = np.array(list(nx.node_connected_component(Graph, v)))
который дает мне список всех индексов узлов в связном компоненте v
в графе Graph
. Я получил желтое предупреждение, когда пытаюсь определить for i in lista:
:
__pyx_t_1 = __pyx_memoryview_fromslice(__pyx_v_lista, 1, (PyObject *(*)(char *)) __pyx_memview_get_long, (int (*)(char *, PyObject *)) __pyx_memview_set_long, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 151, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_1);
if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {
__pyx_t_6 = __pyx_t_1; __Pyx_INCREF(__pyx_t_6); __pyx_t_15 = 0;
__pyx_t_17 = NULL;
} else {
__pyx_t_15 = -1; __pyx_t_6 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 151, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_6);
__pyx_t_17 = Py_TYPE(__pyx_t_6)->tp_iternext; if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 151, __pyx_L1_error)
}
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
for (;;) {
if (likely(!__pyx_t_17)) {
if (likely(PyList_CheckExact(__pyx_t_6))) {
if (__pyx_t_15 >= PyList_GET_SIZE(__pyx_t_6)) break;
#if CYTHON_COMPILING_IN_CPYTHON
__pyx_t_1 = PyList_GET_ITEM(__pyx_t_6, __pyx_t_15); __Pyx_INCREF(__pyx_t_1); __pyx_t_15 ; if (unlikely(0 < 0)) __PYX_ERR(0, 151, __pyx_L1_error)
#else
__pyx_t_1 = PySequence_ITEM(__pyx_t_6, __pyx_t_15); __pyx_t_15 ; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 151, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_1);
#endif
} else {
if (__pyx_t_15 >= PyTuple_GET_SIZE(__pyx_t_6)) break;
#if CYTHON_COMPILING_IN_CPYTHON
__pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_6, __pyx_t_15); __Pyx_INCREF(__pyx_t_1); __pyx_t_15 ; if (unlikely(0 < 0)) __PYX_ERR(0, 151, __pyx_L1_error)
#else
__pyx_t_1 = PySequence_ITEM(__pyx_t_6, __pyx_t_15); __pyx_t_15 ; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 151, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_1);
#endif
}
} else {
__pyx_t_1 = __pyx_t_17(__pyx_t_6);
if (unlikely(!__pyx_t_1)) {
PyObject* exc_type = PyErr_Occurred();
if (exc_type) {
if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
else __PYX_ERR(0, 151, __pyx_L1_error)
}
break;
}
__Pyx_GOTREF(__pyx_t_1);
}
__pyx_t_2 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) amp;amp; PyErr_Occurred())) __PYX_ERR(0, 151, __pyx_L1_error)
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
__pyx_v_i = __pyx_t_2;
/* … */
}
__Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
Очевидно, что код работает, но, поскольку мне нужно использовать эти циклы довольно часто, я хотел бы теперь узнать, как их правильно реализовать.
Какое правильное назначение для lista
?
Комментарии:
1. Что
nx.node_connected_component
возвращает? Это может определить, что вам нужно делать.2. @DavidW возвращает набор.
Ответ №1:
Вам лучше просто перебирать его по индексу
cdef Py_ssize_t i
cdef long val
with cython.boundscheck(False): # these two lines are optional but may increase speed
with cython.wraparound(False):
for i in range(lista.shape[0]):
val = lista[i]
Другая оптимизация, которую вы, вероятно, могли бы сделать, — это определить lista
как
cdef long [::1] lista
в котором говорится, что он непрерывен в памяти.
(Мое первоначальное прочтение вопроса заставило меня подумать, что речь идет о преобразовании из a set
: np.array(list(nx.node_connected_component(Graph, v)))
. Я не думаю, что это то, о чем вы спрашиваете, но в случае, если это так, я не вижу способа ускорить эту строку.)
Комментарии:
1. Я не понимаю одну вещь. Почему мы определяем
val
? Это важно или я могу просто использоватьlista[i]
? И в чем идея cdefPy_ssize_t
? Спасибо2. Вы можете просто использовать
lista[i]
.Py_ssize_t
это целое число со знаком, которое достаточно велико, чтобы использовать его для индексации в любой массив, который может выделить Python. Вы можете использовать любой целочисленный тип, который вам нравится, но еслиlista
он становится слишком длинным, вы можете не дойти до конца.