繁体   English   中英

给定列表而不是范围(N)的Cython有效周期“ for”

[英]Cython efficient cycle 'for' for a given list instead of range(N)

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

当我创建一个整数列表(因为range(N)是,不是吗?)时,例如:

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

这给出了图Graphv的连接组件中节点的所有索引的列表。 当我尝试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的正确分配是哪一个?

最好只按索引遍历

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

指出它在内存中是连续的。

(我对这个问题的初步np.array(list(nx.node_connected_component(Graph, v)))使我认为这是关于从set进行转换的: np.array(list(nx.node_connected_component(Graph, v))) 。我不认为这是您要的内容,但如果是这样,我看不到加快这条线的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM