numpy.sum 可能比 Python for 循环慢

2023-11-25

当对特定轴上的数组求和时,专用数组方法array.sum(ax)实际上可能比 for 循环慢:

v = np.random.rand(3,1e4)

timeit v.sum(0)                             # vectorized method
1000 loops, best of 3: 183 us per loop

timeit for row in v[1:]: v[0] += row        # python loop
10000 loops, best of 3: 39.3 us per loop

向量化方法比普通 for 循环慢 4 倍以上! (wr)on(g) 这里发生了什么,我不能相信 numpy 中的向量化方法比 for 循环更快吗?


不,你不能。正如你有趣的例子指出的那样numpy.sum可能不是最理想的,并且通过显式 for 循环更好的操作布局可能会更有效。

让我再举一个例子:

>>> N, M = 10**4, 10**4
>>> v = np.random.randn(N,M)
>>> r = np.empty(M)
>>> timeit.timeit('v.sum(axis=0, out=r)', 'from __main__ import v,r', number=1)
1.2837879657745361
>>> r = np.empty(N)
>>> timeit.timeit('v.sum(axis=1, out=r)', 'from __main__ import v,r', number=1)
0.09213519096374512

在这里你可以清楚地看到numpy.sum如果对快速运行索引求和(v是 C 连续的),并且在慢速运行轴上求和时不是最佳的。有趣的是,相反的模式适用于for loops:

>>> r = np.zeros(M)
>>> timeit.timeit('for row in v[:]: r += row', 'from __main__ import v,r', number=1)
0.11945700645446777
>>> r = np.zeros(N)
>>> timeit.timeit('for row in v.T[:]: r += row', 'from __main__ import v,r', number=1)
1.2647287845611572

我没有时间检查numpy代码,但我怀疑造成差异的是连续内存访问或跨步访问。

正如这个例子所示,在实现数值算法时,正确的内存布局非常重要。矢量化代码不一定能解决所有问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

numpy.sum 可能比 Python for 循环慢 的相关文章