Почему `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" раз и навсегда и используйте ее во всем своем коде, чтобы сохранить создание объекта)