繁体   English   中英

如果单个整数具有 python-native int 类型,则将单个整数更快地添加到 numpy 数组

[英]Adding single integer to numpy array faster if single integer has python-native int type

我将一个整数添加到具有 1000 个元素的整数数组中。 当我第一次将单个整数从numpy.int64转换为 python-native int时,这快了 25%。

为什么? 作为一般的经验法则,我是否应该将单个数字转换为原生 python 格式,以便使用大约这个大小的数组进行单数到数组的操作?

注意:可能与我之前的问题Conjugating a complex number much faster if number has python-native complex type有关。

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-changeshttps://github。 com/numpy/numpy/pull/21188 我正在使用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))非常慢?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM