Cython高效循环'用于'对于给定的列表而不是范围(N)

时间:2016-10-12 08:08:49

标签: python python-2.7 optimization cython

我在cython(python 2.7)上进行编码,并且我正在处理'对于'周期。只要我使用标准for i in range(N),我就会得到一个很酷的代码:在cythonized code.html上没有黄色警告。

当我创建一个整数列表时(因为范围(N)是,isn'它?),例如:

cdef long [:] lista = np.array(list(nx.node_connected_component(Graph, v)))

它给出了图vGraph的连通分量中节点的所有索引的列表。当我尝试定义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) && 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 个答案:

答案 0 :(得分:0)

你最好只通过索引

循环它
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

表明它在记忆中是连续的。

(我对这个问题的初步解读让我觉得这是关于setnp.array(list(nx.node_connected_component(Graph, v)))的转换。我不认为这是你所要求的,但万一是的,我看不出加速这条线的方法。)