使用nogi在Cython中处理列表列表

2024-03-29 06:59:09 发布

您现在位置:Python中文网/ 问答频道 /正文

在Python中,我有一个列表作为输入:

input = [[0,1,2],[0,3,4,5],[0,6]]

实际上,子列表的数量是上万个。每个子列表的长度可能会有很大的变化,从零或一个值到几百。在

我想把输入数据作为二维结构传递给一个Cython模块来处理它。我希望在多个核心上处理数据,因此我将prangenogil=True一起使用:

^{pr2}$

我看到了以下解决方案:

  1. 将列表放入2D数组中。但是由于每个子列表的长度变化很大,因此ndarray不是一个理想的数据结构
  2. 修改my_func以接受列表列表。问题是部分代码在没有GIL的情况下执行,因此无法访问python对象。在

有人对如何解决这个问题有什么建议,最好是代码方面的建议?在


Tags: 模块数据代码true核心列表input数量
1条回答
网友
1楼 · 发布于 2024-03-29 06:59:09

我可能会使用扁平数组,其中单个列表的开头存储在一个辅助数组中,而不是与csr-matrices不相似。在

下面是一个如何从列表列表(使用numpy,但您也可以使用array.array;它也不是真正针对速度进行优化)来构造此数据结构的示例,只是为了给您一个想法:

import numpy as np
def flatten_list_of_lists(lst_of_lsts):
    N = sum(map(len, lst_of_lsts))  # number of elements in the flattened array   
    starts = np.empty(len(lst_of_lsts)+1, dtype=np.uint64)  # needs place for one sentinel
    values = np.empty(N, dtype=np.int64)

    starts[0], cnt = 0, 0
    for i,lst in enumerate(lst_of_lsts):
        for el in lst:
            values[cnt] = el
            cnt += 1       # update index in the flattened array for the next element
        starts[i+1] = cnt  # remember the start of the next list

    return starts, values

因此,对于您的示例,将产生以下结果:

^{pr2}$

您可以看到:有3个子列表以037开始,并且是3(差异starts[1]-starts[0])、42元素。在

这就是如何使用这些数据:

%%cython
from cython.parallel import prange

cpdef int my_func(unsigned long long[::1] starts, long long[::1] values):
    cdef int i,j
    for i in prange(len(starts)-1, nogil=True):
        for j in range(starts[i], starts[i+1]):
                    # Do something with values[j]
            pass
    return 42

相关问题 更多 >