Почему `numpy` медленнее, чем python для сдвигов влево?

Я пытаюсь сделать немного сдвигов на numpy целые числа (в частности, numpy.uint64 объекты), и мне нужно, чтобы они были быстрыми. В моей реализации ниже, я поместил объект в numpy.array только потому, что это единственный объект, который может принимать сдвиги влево. Если есть более быстрая реализация, я приму это.

from timeit import timeit
print(timeit("a << 1", "a = int(2**60)"))
print(timeit("a << 1", "import numpy as np; a = np.array([2 ** 60], dtype=np.uint64)"))
print(timeit("np.left_shift(a, 1)", "import numpy as np; a = np.array([2 ** 60], dtype=np.uint64)"))

возвращает:

0.056681648000000084
1.208092987
1.1685176299999998

Почему Python намного быстрее, чем numpy для этой операции? Есть ли способ получить сопоставимые скорости в numpy?

1 ответ

Решение

Что касается разницы в производительности, то это кажется логичным: вы применяете векторизованный сдвиг для одного элемента. Есть огромные накладные расходы, просто достигающие сменной части и изменяющие структуру. нативный код сдвигается быстрее.

Хорошо, я погуглил сообщение об ошибке, которое появляется при попытке сделать это для одного элемента, а именно:

>>> a = numpy.uint64(2**60)
>>> a << 3
Traceback (most recent call last):
  File "<string>", line 301, in runcode
  File "<interactive input>", line 1, in <module>
TypeError: ufunc 'left_shift' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

и я нашел эту проблему GitHub: https://github.com/numpy/numpy/issues/2524

Это связано с тем, что число смещения преобразуется в тип со знаком, и нет целочисленного типа со знаком, достаточно большого для хранения uint64.

Теперь хороший обходной путь (как видно из этого комментария к выпуску github) заключается в следующем:

a << numpy.uint64(1)

(возможно, создайте константу "1" раз и навсегда и используйте ее во всем своем коде, чтобы сохранить создание объекта)

Другие вопросы по тегам