我正在寻找最有效的方法来确定大型数组包含至少一个非零值。乍一看np.任何
看起来像是这显然是一种工具,但在大型阵列上运行速度似乎出乎意料地慢。
考虑这种极端情况:
first=np.zeros(1E3,dtype=np.bool)last=np.zeros(1E3,dtype=np.bool)first[0]=真last[-1]=真#测试1%timeit np.any(第一个)>>>100000个回路,三选一:每个回路6.36 us#测试2%timeit np.any(最后)>>>100000个回路,每回路最佳3:6.95 us
至少不适用
似乎在做一些模糊合理的事情-如果非零值是数组中的第一个值,不需要考虑回来之前还有其他的吗真的
,所以我希望测试1稍微比测试2快。
然而,当我们将数组变得更大时会发生什么?
第一个=np.零(1E9,数据类型=np.bool)last=np.zeros(1E9,dtype=np.bool)first[0]=真last[-1]=真#测试3%timeit np.any(第一个)>>>10个回路,最好为3:21.6 ms/回路#测试4%timeit np.any(最后)>>>1个回路,每个回路最好为3:739 ms
正如预期的那样,测试4比测试3慢得多。然而,在测试3中np.任何
仍然只需检查中单个元素的值第一
为了知道它至少包含一个非零值。为什么?那么,测试3比测试1慢得多吗?
编辑1:
我使用的是Numpy的开发版本(1.8.0.dev-e11cd9b),但我使用Numpy 1.7.1获得了完全相同的计时结果。我运行的是64位Linux,Python 2.7.4。我的系统基本上处于空闲状态(我正在运行IPython会话、浏览器和文本编辑器),我肯定没有进行交换。我还在另一台运行Numpy 1.7.1的机器上复制了结果。
编辑2:
使用Numpy 1.6.2,测试1和测试3的时间都是~1.85us,因此正如jorgeca所说,Numpy 1.6.2和1.7.11.7.0。
编辑3:
在J.F.Sebastian和jorgeca的带领下,我使用np.全部
在一个零数组上,它应该等价于调用np.任何
在第一个元素为一的数组上。
测试脚本:
导入timeit将numpy导入为np打印“Numpy v%s”%np.version.full_versionstmt=“np.all(x)”对于xrange(10)中的ii:setup=“将numpy导入为np;x=np.zeros(%d,dtype=np.bool)”%(10**ii)timer=计时。计时器(语句、设置)n、 r=1,3t=np.min(计时器重复(r,n))当t<0.2时:n*=10t=np.min(计时器重复(r,n))t/=n如果t<1E-3:timestr=“%1.3f我们”%(t*1E6)elif t<1:时间tr=“%1.3f毫秒”%(t*1E3)其他:timestr=“%1.3f s”%t打印“数组大小:1E%i,%i循环,%i:%s/loop中的最佳”%(ii,n,r,timestr)
结果:
Numpy 1.6.2版阵列大小:1E0,1000000个环路,三选一:1.738 us/环路阵列大小:1E1000000个环路,三选一:1.845 us/环路阵列大小:1E2,1000000个环路,三选一:1.862 us/环路阵列大小:1E3,1000000个环路,三选一:1.858 us/环路阵列大小:1E4,1000000个环路,三选一:1.864 us/环路阵列大小:1E5,1000000个环路,三选一:1.882 us/环路阵列大小:1E6,1000000个环路,三选一:1.866 us/环路阵列大小:1E7,1000000个环路,三选一:1.853 us/环路阵列大小:1E8,1000000个环路,三选一:1.860 us/环路阵列大小:1E9,1000000个环路,三选一:1.854 us/环路Numpy 1.7.0版阵列大小:1E0,100000个环路,三选一:5.881 us/环路阵列大小:1E1,100000个环路,三选一:5.831 us/环路阵列大小:1E2,100000个环路,三选一:5.924 us/环路阵列大小:1E3,100000个环路,三选一:5.864 us/环路阵列大小:1E4,100000个环路,三选一:5.997 us/环路阵列大小:1E5,100000个环路,三局三胜制:6.979 us/环路阵列大小:1E6,100000个环路,三选一:17.196 us/环路阵列大小:1E7,10000个环路,最好的3:116.162 us/环路阵列大小:1E8,1000个环路,最佳3:1.112 ms/环路阵列大小:1E9,100个环路,三选一:11.061 ms/环路Numpy v1.7.1版阵列大小:1E0,100000个环路,三选一:6.216 us/环路阵列大小:1E1,100000个环路,三取三:6.257 us/环路阵列大小:1E2,100000个环路,三选一:6.318 us/环路阵列大小:1E3,100000个环路,三选一:6.247 us/环路阵列大小:1E4,100000个环路,三选一:6.492 us/环路阵列大小:1E5,100000个环路,三选一:7.406 us/环路阵列大小:1E6,100000个环路,三选一:17.426 us/环路阵列大小:1E7,10000个环路,三选一:115.946 us/环路阵列大小:1E8,1000个环路,最佳3:1.102 ms/环路阵列大小:1E9,100个环路,三选一:10.987 ms/环路Numpy v1.8.0.dev-e11cd9b版阵列大小:1E0,100000个环路,三选一:6.357 us/环路阵列大小:1E1,100000个环路,三取三:6.399 us/环路阵列大小:1E2,100000个环路,三选一:6.425 us/环路阵列大小:1E3,100000个环路,三选一:6.397 us/环路阵列大小:1E4,100000个环路,三选一:6.596 us/环路阵列大小:1E5,100000个环路,三选一:7.569 us/环路阵列大小:1E6,100000个环路,三选一:17.445 us/环路阵列大小:1E7,10000个环路,三选一:115.109 us/环路阵列大小:1E8,1000个环路,三选一:1.094 ms/环路阵列大小:1E9,100个环路,三选一:10.840 ms/环路
编辑4:
在seberg的评论之后,我用一个净浮动32
数组而不是np.池
在这种情况下,Numpy 1.6.2也会随着阵列大小的增加而减速:
Numpy 1.6.2版阵列大小:1E0,100000个环路,三选一:3.503 us/环路阵列大小:1E1,100000个环路,三选一:3.597 us/环路阵列大小:1E2,100000个环路,三选一:3.742 us/环路阵列大小:1E3,100000个环路,三选一:4.745 us/环路阵列大小:1E4,100000个环路,三取三:14.533 us/环路阵列大小:1E5,10000个环路,最好的3:112.463 us/环路阵列大小:1E6,1000个环路,最佳3:1.101 ms/环路阵列大小:1E7,100个环路,三选一:11.724 ms/环路阵列大小:1E8,10个环路,最好为3:116.924 ms/环路阵列大小:1E9,1个环路,最好为3:1.168 s/环路Numpy v1.7.1版阵列大小:1E0,100000个环路,三取三:6.548 us/环路阵列大小:1E1,100000个环路,三选一:6.546 us/环路阵列大小:1E2,100000个环路,三选一:6.804 us/环路阵列大小:1E3,100000个环路,三选一:7.784 us/环路阵列大小:1E4,100000个环路,三选一:17.946 us/环路阵列大小:1E5,10000个环路,最好的3:117.235 us/环路阵列大小:1E6,1000个环路,三选一:1.096 ms/环路阵列大小:1E7,100个环路,三选一:12.328 ms/环路阵列大小:1E8,10个环路,3中最佳:118.431 ms/环路阵列大小:1E9,1个环路,最好为3:1.172 s/环路
为什么会发生这种情况?与布尔情况一样,np.全部
在返回之前,仍然只需要检查第一个元素,因此时间应该仍然是恒定的w.r.t.数组大小。