我向一个有1000个元素的整数数组中添加一个整数。如果我先将单个整数从numpy.int64
转换为本地的Python类型int
,这会更快25%。
为什么?作为一个经验法则,我是否应该将单个数字转换为本地 Python 格式,以便在处理大约此大小的数组时进行单个数字到数组操作?
注:可能与我的先前问题“如果数字具有本地 Python 复杂类型,则共轭复数的速度要快得多”相关。
import numpy as np
nnu = 10418
nnu_use = 5210
a = np.random.randint(nnu,size=1000)
b = np.random.randint(nnu_use,size=1)[0]
%timeit a + b # --> 3.9 µs ± 19.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit a + int(b) # --> 2.87 µs ± 8.07 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
请注意,即使是标量到标量的操作,加速比也可能非常巨大(50倍),如下所示:
np.random.seed(100)
a = (np.random.rand(1))[0]
a_native = float(a)
b = complex(np.random.rand(1)+1j*np.random.rand(1))
c = (np.random.rand(1)+1j*np.random.rand(1))[0]
c_native = complex(c)
%timeit a * (b - b.conjugate() * c) # 6.48 µs ± 49.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit a_native * (b - b.conjugate() * c_native) # 283 ns ± 7.78 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit a * b # 5.07 µs ± 17.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit a_native * b # 94.5 ns ± 0.868 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
更新:最新的numpy版本是否修复了速度差异?numpy 1.23
的发布说明中提到标量运算现在更快,详见https://numpy.org/devdocs/release/1.23.0-notes.html#performance-improvements-and-changes和https://github.com/numpy/numpy/pull/21188。我正在使用python 3.7.6, numpy 1.21.2
。
b
是通过引用传递的,而int(b)
是按值传递的,并且两者采用不同的代码路径。这可以解释方差差异,因为按值传递的版本通常更易于缓存,也可能解释平均差异。另一个表明这可能是情况的指标是b
具有内部缓冲区(memoryview(b)
有效),并且您可以像处理任何其他ndarray一样检查b.flags
。 - FirefoxMetzger