В настоящее время я пытаюсь ускорить процедуру Cython, которая сильно зависит от списков. В основном, я хотел бы увеличить скорость индексации в этих списках.
Согласно документации, рекомендуется использовать массивы Numpy с представлениями памяти.
https://cython.readthedocs.io/en/latest/src/userguide/memoryviews.html
Однако, когда я изменяю свои списки на пустые массивы (большинство из них просто целые числа), код становится намного медленнее.
Я хотел бы лучше понять, почему это происходит, поскольку я ожидаю, что массивы будут намного быстрее, чем списки.
Я не могу показать точный код, над которым я работаю, но я буду использовать пример, чтобы передать мою проблему.
Итак, допустим, у меня есть эти три функции, которые подсчитывают количество элементов в списке.
Пример: если список:
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
Почему это происходит? Как это стало намного медленнее?
Спасибо!