为何np.dot比np.sum快得多?NumPy数组求和性能探究
为什么np.dot的运行速度远快于np.sum?
我们知道np.sum速度较慢,存在更快的替代方案,比如数组实例方法sum()或者np.add.reduce()。以下是小数组(长度1000)的性能测试:
In [20]: A = np.random.rand(1000) In [21]: B = np.random.rand(1000) In [22]: %timeit np.sum(A) 3.21 µs ± 270 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each) In [23]: %timeit A.sum() 1.7 µs ± 11.5 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each) In [24]: %timeit np.add.reduce(A) 1.61 µs ± 19.6 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
但这些方法的速度都不及np.dot:
In [25]: %timeit np.dot(A,B) 1.18 µs ± 43.9 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
既然np.dot需要先对两个数组逐元素相乘再求和,为何它的速度会快于仅对单个数组求和?如果将B设为全1数组,np.dot(A, B)的作用就等同于对A求和,此时测试结果显示它仍是最快的:
In [26]: O = np.ones(1000) In [27]: %timeit np.dot(A,O) 1.16 µs ± 6.37 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
这看起来不太合理,不是吗?
测试环境
- 系统:Ubuntu
- NumPy版本:1.24.2(使用openblas64)
- Python版本:3.10.6
- 支持的SIMD扩展:
baseline = SSE,SSE2,SSE3 found = SSSE3,SSE41,POPCNT,SSE42,AVX,F16C,FMA3,AVX2
更新:大数组下的性能反转
当数组长度大幅增加到100万时,性能测试结果的顺序会反转:
In [28]: A = np.random.rand(1000000) In [29]: O = np.ones(1000000) In [30]: %timeit np.dot(A,O) 545 µs ± 8.87 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each) In [31]: %timeit np.sum(A) 429 µs ± 11 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each) In [32]: %timeit A.sum() 404 µs ± 2.95 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each) In [33]: %timeit np.add.reduce(A) 401 µs ± 4.21 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
这表明np.sum(A)、A.sum()、np.add.reduce(A)存在某种固定开销,而np.dot没有,但实际求和部分的代码速度更快。
欢迎分享使用Cython、Numba、Python等实现的性能优化方案。
内容的提问来源于Stack Exchange,提问作者Simd
相关产品推荐
相关产品推荐

