Numpy:为什么arr.mean()比arr.sum()/arr.size慢?



我使用timeit模块测量了计算numpy数组(1D和2D)平均值的两个等效函数的运行时间:

>>> setup = 'import numpy as np;a=np.random.randint(100, size=(100,100));b=np.random.randint(100, size=1000)'
>>> timeit.timeit(setup=setup, stmt='a.mean()')
13.513522000001103
>>> timeit.timeit(setup=setup, stmt='a.sum()/a.size')
6.080089200000657
>>> timeit.timeit(setup=setup, stmt='b.mean()')
5.404982399999426
>>> timeit.timeit(setup=setup, stmt='b.sum()/b.size')
2.261378399998648

令人惊讶的是,无论数组大小如何,numpy.ndarray.mean方法都比numpy.ndarray.sum()/numpy.ndarray.size方法慢。

有人能解释一下吗?提前感谢!

np.sumnp.mean在内部对不同的本机数据类型进行操作. 实际上,np.mean在内部将所有项转换为np.float64类型,因此创建了一个昂贵的新临时数组。np.sum直接操作np.int32整数(在主流x86-64处理器上可以更有效地计算)。为了模拟np.mean的行为,可以使用b.sum(dtype=np.float64)/b.size指定累加器/输出类型。最终的性能更接近np.mean。关于这方面的更多信息,请考虑阅读这篇文章和这篇文章。注意np.sum可能会出现溢出如果整数很大(导致与np.mean相反的完全错误的结果)。

另外,np.mean更高的(常量)开销由于它在内部实现的方式(它做了一个泛型缩减,并且有更多的检查和函数调用)。这个开销对于几乎所有Numpy函数都是固有的,但是对于某些函数来说可能要大得多。这部分可以优化,我们之前做了一些工作来减少它,但是很多代码需要修改以使它更快,到目前为止它还不是一个临界点(Numpy不是设计用来操作非常小的数组的,因为CPython会导致大量的检查)。如果您将数组大小设置为200_000,那么b.mean()b.sum(dtype=np.float64)/b.size的执行时间应该非常接近(这就是我的机器上的情况)。

相关内容

  • 没有找到相关文章

最新更新