提问人:bproxauf 提问时间:7/21/2022 最后编辑:bproxauf 更新时间:7/22/2022 访问量:269
如果单个整数具有 python-native int 类型,则更快地将单个整数添加到 numpy 数组
Adding single integer to numpy array faster if single integer has python-native int type
问:
我将一个整数添加到具有 1000 个元素的整数数组中。当我第一次将单个整数从 python-native 强制转换为 python-native 时,这快了 25%。numpy.int64
int
为什么?作为一般经验法则,我是否应该将单个数字转换为本机 python 格式,以便使用大约此大小的数组进行单数字到数组的操作?
注意:可能与我之前的问题有关 如果数字具有 python-native 复数类型,则复数共轭速度要快得多。
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 的发行说明提到标量运算现在快得多,参见 https://numpy.org/devdocs/release/1.23.0-notes.html#performance-improvements-and-changes 和 https://github.com/numpy/numpy/pull/21188。我正在使用 .1.23
python 3.7.6, numpy 1.21.2
答:
在装有 CPython 3.8.1 的 Windows PC 上,我得到:
[Old] Numpy 1.22.4:
- First test: 1.65 µs VS 1.43 µs
- Second: 2.03 µs VS 0.17 µs
[New] Numpy 1.23.1:
- First test: 1.38 µs VS 1.24 µs <---- A bit better than Numpy 1.22.4
- Second: 0.38 µs VS 0.17 µs <---- Much better than Numpy 1.22.4
虽然新版本的 Numpy 提供了很好的提升,但原生类型应该始终比具有(默认)CPython 解释器的 Numpy 更快。实际上,解释器需要调用 Numpy 的 C 函数。本机类型不需要这样做。此外,Numpy 检查和包装不是最佳的,但 Numpy 一开始就不是为快速标量计算而设计的(尽管开销以前并不合理)。事实上,标量计算效率非常低,解释器会阻止任何快速执行。
如果您计划进行许多标量操作,则需要使用本机编译的代码,可能使用 Cython、Numba 甚至原始 C/C++ 模块。请注意,Cython 不会优化/内联 Numpy 调用,但可以更快地对本机类型进行操作。本机代码当然可以在少一个甚至两个数量级的时间内做到这一点。
请注意,在第一种情况下,Numpy 函数中的路径不同,并且 Numpy 会进行额外的检查,这些检查的成本会稍微高一些,然后该值不是 CPython 对象。尽管如此,它应该是一个恒定的开销(现在相对较小)。否则,这将是一个错误(应该报告)。
相关新闻: 为什么 np.sum(range(N))
很慢?
下一个:移位插值未给出预期行为
评论
b
int(b)
b
memoryview(b)
b.flags