【发布时间】:2019-12-12 05:52:16
【问题描述】:
考虑以下简单测试:
import numpy as np
from timeit import timeit
a = np.random.randint(0,2,1000000,bool)
让我们找到第一个True的索引
timeit(lambda:a.argmax(), number=1000)
# 0.000451055821031332
这相当快,因为numpy 短路了。
它也适用于连续切片,
timeit(lambda:a[1:-1].argmax(), number=1000)
# 0.0006490410305559635
但似乎不是在非连续的。我主要感兴趣的是找到最后一个True:
timeit(lambda:a[::-1].argmax(), number=1000)
# 0.3737605109345168
更新:我认为观察到的减速不是由于短路引起的假设是不准确的(感谢@Victor Ruiz)。的确,在 所有
False数组的最坏情况
b=np.zeros_like(a)
timeit(lambda:b.argmax(), number=1000)
# 0.04321779008023441
我们仍然比非连续的快一个数量级 案子。我已经准备好接受维克多的解释,即真正的罪魁祸首 正在制作副本(使用
.copy()强制复制的时间是 暗示)。之后是否真的不再重要 短路发生与否。
但其他步长 != 1 会产生类似的行为。
timeit(lambda:a[::2].argmax(), number=1000)
# 0.19192566303536296
问题:为什么numpy 在最后两个示例中没有短路UPDATE 不复制?
而且,更重要的是:是否有解决方法,即强制numpy 短路更新 不复制也在非连续数组上?
【问题讨论】:
-
我隐约记得很久以前看过 SO 的这种短路。它适用于 bool 和浮点数中的
nan。我认为它是在 C 代码中的非常低级别实现的,所以 Victor 认为你的跨步创建副本的想法是有道理的。 -
选择一个好的短路测试对象可能很棘手。您是否希望它在迭代的早期、中间或结束时退出。如果发生短路,时间会有所不同。
-
@hpaulj “所以维克多认为你的步伐创造了副本的想法是有道理的。”时间当然支持它。
标签: python numpy short-circuiting