我目前正在尝试加快Cython例程的速度,该例程高度依赖列表。通常,我想提高这些列表上索引的速度。
根据文档,建议将Numpy数组与memoryviews一起使用。
https://cython.readthedocs.io/en/latest/src/userguide/memoryviews.html
但是,当我将列表更改为numpy数组(它们中的大多数只是整数)时,代码会变慢。 我想更好地理解为什么会这样,因为我希望数组会比列表快得多。
我无法显示我正在使用的确切代码,但是我将使用一个示例来传达我的问题。
所以可以说我有这三个函数,它们计算列表中元素的数量。 示例:如果列表为:
test_list = [1, 2, 3, 4, 1, 1, 3, 4]
然后输出为[3,1,2,2]。
def counter(test_list):
""" The Counter was imported from collections naturally """
output = [0] * len(set(test_list))
for key, value in Counter(test_list).items():
output[key - 1] = value
return output
现在有两个计算相同内容的cython函数:
def cython_counter_collections(test_list):
cdef int key, value
output = [0] * len(set(test_list))
for key, value in Counter(test_list).items():
output[key - 1] = value
return output
和
def cython_counter_manual(test_list):
cdef long[:] new_test_list = np.array(test_list)
cdef int size, val, i, uniques_size
size = new_test_list.shape[0]
uniques_size = np.unique(new_test_list).shape[0]
i = 0
output = [0] * uniques_size
while i < size:
val = new_test_list[i]
output[val-1] += 1
i+=1
return output
对于最后一个函数,我使用import和cimport numpy作为np。
我假设最后一个函数cython_counter_manual将被禁闭,因为我使用的是numpy数组,并且不使用任何Python调用。 例如,我使用timeit来测量时间
print(timeit("counter(test_list)", globals=globals(), number=n_its))
所有功能的结果为:
Python Code
3.12014272399756 s
Cython Counter Collections
2.883361326999875 s
Cython Counter Manual
11.205707081000583 s
为什么会这样?它怎么变得这么慢? 谢谢!