迭代与Cython并行的列表

cls*_*udt 9 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
Run Code Online (Sandbox Code Playgroud)

这会产生很多编译器错误,因为没有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
Run Code Online (Sandbox Code Playgroud)

Ian*_*anH 7

我不知道有什么方法可以做到这一点.列表是Python对象,因此使用其__getitem__方法需要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
Run Code Online (Sandbox Code Playgroud)

在我的机器上,对于这种特殊情况,prange并不比普通循环更快,但在其他情况下它可以更好地工作.有关如何使用prange的更多信息,请参阅http://docs.cython.org/src/userguide/parallelism.html上的文档.

是否可以使用数组取决于您更改数组大小的程度.如果您需要大小的灵活性,阵列将无法正常工作.您还可以尝试使用vectorC++ 与类进行交互.我自己从来没有这样做过,但是这里有一个如何做到的简要说明:http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html#nested-class-declarations