Python 与Cython并行迭代列表

Python 与Cython并行迭代列表,python,parallel-processing,openmp,cython,Python,Parallel Processing,Openmp,Cython,如何在Cython中并行迭代(Python)列表 考虑以下简单函数: def sumList(): cdef int n = 1000 cdef int sum = 0 ls = [i for i in range(n)] cdef Py_ssize_t i for i in prange(n, nogil=True): sum += ls[i] return sum 这会导致许多编译器错误,因为没有GIL的并行部分显然无法

如何在Cython中并行迭代(Python)列表

考虑以下简单函数:

def sumList():
    cdef int n = 1000
    cdef int sum = 0

    ls = [i for i in range(n)]

    cdef Py_ssize_t i
    for i in prange(n, nogil=True):
        sum += ls[i]

    return sum
这会导致许多编译器错误,因为没有GIL的并行部分显然无法处理任何Python对象:

Error compiling Cython file:
------------------------------------------------------------
...

    ls = [i for i in range(n)]

    cdef Py_ssize_t i
    for i in prange(n, nogil=True):
        sum += ls[i]
     ^
------------------------------------------------------------

src/parallel.pyx:42:6: Coercion from Python not allowed without the GIL

Error compiling Cython file:
------------------------------------------------------------
...

    ls = [i for i in range(n)]

    cdef Py_ssize_t i
    for i in prange(n, nogil=True):
        sum += ls[i]
     ^
------------------------------------------------------------

src/parallel.pyx:42:6: Operation not allowed without gil

Error compiling Cython file:
------------------------------------------------------------
...

    ls = [i for i in range(n)]

    cdef Py_ssize_t i
    for i in prange(n, nogil=True):
        sum += ls[i]
     ^
------------------------------------------------------------

src/parallel.pyx:42:6: Converting to Python object not allowed without gil

Error compiling Cython file:
------------------------------------------------------------
...

    ls = [i for i in range(n)]

    cdef Py_ssize_t i
    for i in prange(n, nogil=True):
        sum += ls[i]
          ^
------------------------------------------------------------

src/parallel.pyx:42:11: Indexing Python object not allowed without gil

我不知道有什么办法可以做到这一点。列表是一个Python对象,因此使用它的
\uu getitem\uu
方法需要GIL。在这种情况下,如果您能够使用NumPy数组,那么它将起作用。例如,如果要迭代双精度浮点值数组
A
,可以执行以下操作:

cimport cython
from numpy cimport ndarray as ar
from cython.parallel import prange
@cython.boundscheck(False)
@cython.wraparound(False)
cpdef cysumpar(ar[double] A):
    cdef double tot=0.
    cdef int i, n=A.size
    for i in prange(n, nogil=True):
        tot += A[i]
    return tot
在我的机器上,对于这种特殊情况,prange并没有使它比普通循环更快,但在其他情况下它可以工作得更好。有关如何使用prange的更多信息,请参阅


是否可以使用数组取决于更改数组大小的程度。如果在大小方面需要很大的灵活性,那么阵列将无法工作。还可以尝试在C++中与向量类进行接口。我自己从来没有这样做过,但这里有一个关于如何做的简要描述:

如果需要任何数值,请将列表转换为数组;如果值限制在0到255之间,请将其转换为bytearray。如果存储的不是数值,请尝试numpy或直接使用数据类型。例如,对于字节:

cdef int[::1] gen = array.array('i',[1, 2, 3, 4])
如果您想使用C类型:


ctypedef unsigned char uint8\u t

另一方面,如果您只需要求和,您也可以使用NumPy数组的
sum
方法。谢谢您的提示。sum只是一个简单的例子,我需要并行应用更复杂的操作。对,任何涉及使用Python解释器的操作都不能在nogil上下文中使用,因为解释器不是线程安全的。这适用于NumPy的大多数事情。Cython可以在类似这样的情况下删除Python调用以进行单项访问,然后您会得到相当于C循环的结果?它是c语法,类似于列表上的并行迭代(D中的数组或范围),如果您熟悉的话,它几乎和在MATLAB中实现一样简单。请在此处查看示例:。我发现从Python背景很容易理解。@mattyTpain从未尝试过D,请看一看。@mattyTpain尝试过D,喜欢Python语法。但我遇到了一个问题: