【问题标题】:Why is `numpy` slower than python for left bit shifts?为什么 numpy 的左位移比 python 慢?
【发布时间】:2019-03-17 20:40:14
【问题描述】:

我正在尝试对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 中获得相当的速度?

【问题讨论】:

  • 您正在对一个元素应用矢量化移位。到达 shift 部分并更改 numpy 结构会产生很大的开销。本机代码转换得更快。但是,如果您进行 10000 次轮班,那将会改变
  • 您建议如何加快速度? a &lt;&lt; 1 不适用于 numpy uint64,除非对象在数组中
  • 听起来有限制:github.com/numpy/numpy/issues/2524
  • 如果 Numba 适合您,您也可以尝试类似的方法。 stackoverflow.com/a/45070947/4045774

标签: python numpy


【解决方案1】:

关于性能差异,这似乎是合乎逻辑的:您正在对一个元素应用矢量化移位。到达 shift 部分并更改 numpy 结构会产生很大的开销。本机代码的转换速度更快。

好的,当您尝试在一个元素上执行此操作时,我搜索了您收到的错误消息,即:

>>> 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 issue comment 所示)是这样的:

a << numpy.uint64(1)

(也许一劳永逸地构建“1”常量并在所有代码中使用它来保存对象创建)

【讨论】:

  • 用这条评论更新你的答案,我会给你一个绿色的复选标记:github.com/numpy/numpy/issues/2524#issuecomment-348538957 这个答案在速度上是相当的——我正在写这个答案。
  • 标量/数组移位情况有效,因为如果可能在混合标量/数组操作中,标量被“降级”为更小的类型,必要时通过一些特殊处理来选择无符号类型。见numpy.result_type
  • 肯定存在混淆的风险,我更愿意明确类型而不是依赖它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-03
  • 2017-11-09
  • 2013-12-07
  • 2014-08-10
  • 2018-01-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多