Cython 迭代 numpy 数组列表而不使用 gil

use*_*195 5 c python numpy cython

我想迭代具有不同维度的 numpy 数组列表,并将它们传递给不需要 GIL 的 cython 函数:

# a has T1 rows and M columns
a = np.array([[0.0, 0.1, 0.3, 0.7],
              [0.1, 0.2, 0.1, 0.6],
              [0.1, 0.2, 0.1, 0.6]])

# b has T2 rows and M columns
b = np.array([[1.0, 0.0, 0.0, 0.0],
              [0.1, 0.2, 0.1, 0.6]])

# c has T3 rows and M columns
c = np.array([[0.1, 0.0, 0.3, 0.6],
              [0.5, 0.2, 0.3, 0.0],
              [0.0, 1.0, 0.0, 0.0],
              [0.0, 0.0, 0.1, 0.0]])

array_list = [a, b, c]
N = len(array_list)

# this function works
@cython.boundscheck(False)
@cython.wraparound(False)
cdef void function_not_requiring_the_gil(double[:, ::1] arr) nogil:
    cdef int T = arr.shape[0]
    cdef int M = arr.shape[1]
    cdef int i, t

    for t in range(T):
        for i in range(M):
            # do some arbitrary thing to the array in-place
            arr[t, i] += 0.001

# issue is with this function
def function_with_loop_over_arrays(array_list, int N):
    cdef int i

    with nogil:
        for i in range(N):
            function_not_requiring_the_gil(array_list[i])
Run Code Online (Sandbox Code Playgroud)

当我编译 Cython 代码时,出现以下错误:

Error compiling Cython file:
------------------------------------------------------------
...
def function_with_loop_over_arrays(array_list, int N):
    cdef int i

    with nogil:
        for i in range(N):
            function_not_requiring_the_gil(array_list[i])                                                    ^
------------------------------------------------------------

my_file.pyx:312:53: Indexing Python object not allowed without gil
Run Code Online (Sandbox Code Playgroud)

是否有另一种类型的数据结构可以代替 Python 列表来存储这些 numpy 数组,以便我可以在没有 gil 的情况下迭代它们?我愿意接受涉及 malloc C 指针/Cython 内存视图/我不知道的其他类型的建议。

请注意,每个 numpy 数组都有不同的行数,但数组列表的长度是已知的。

P. *_*eri 3

您可以将两个形状数组传递(3,)function_with_loop_over_arrays:one( ),其中包含指向,和array_starts的第一个元素的指针,one( ) 包含,和。abcarrays_rowsT1T2T3

然后进行修改,function_not_requiring_the_gil以便它接收数组第一个元素及其行数的指针,您将能够使用以下命令调用它function_with_loop_over_arrays

for i in range(N):  # N is 3 and should be passed to function_with_loop_over_arrays
    function_not_requiring_the_gil(array_starts[i], array_rows[i])  
Run Code Online (Sandbox Code Playgroud)