我将一个整数添加到包含numpy.int640个元素的整数数组中.当我第一次将单个整数从numpy.int64转换为python本机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)

请注意,对于标量到标量的操作,速度可能会非常快(factor 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)

Update:是不是最新的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 interpreter的Numpy快.实际上,解释器需要调用Numpy的C函数.本机类型不需要这样做.此外,Numpy判断和包装不是最优的,但Numpy最初不是为快速标量计算而设计的(尽管之前的开销不合理).事实上,标量计算效率非常低,解释器阻止任何快速执行.

如果计划执行许多标量操作,则需要使用本机编译的代码,可能使用Cython、Numba,甚至是原始C/C++模块.注意,Cython不优化/内联Numpy调用,但可以更快地在本机类型上操作.本机代码当然可以在一个或两个数量级的时间内完成这项工作.

注意,在第一种情况下,Numpy函数中的路径不同,Numpy执行额外的判断,这比值不是CPython对象要贵一些.不过,它应该是一个恒定的开销(现在相对较小).否则,这将是一个bug(应该报告).

相关:Why is np.sum(range(N)) very slow?

Python相关问答推荐

我可以使用极点优化这个面向cpu的pandas代码吗?

为什么我的(工作)代码(生成交互式情节)在将其放入函数中时不再工作?

pyramid 内部数组中的连续序列-两极

code _tkinter. Tcl错误:窗口路径名称错误.!按钮4"

基本链合同的地址是如何计算的?

覆盖Django rest响应,仅返回PK

Pandas :多索引组

如何在Python中使用时区夏令时获取任何给定本地时间的纪元值?

LAB中的增强数组

Python会扔掉未使用的表情吗?

ModuleNotFound错误:没有名为flags.State的模块; flags不是包

Python 约束无法解决n皇后之谜

如何使用根据其他值相似的列从列表中获取的中间值填充空NaN数据

如何在Polars中从列表中的所有 struct 中 Select 字段?

在ubuntu上安装dlib时出错

如何使用Pandas DataFrame按日期和项目汇总计数作为列标题

如何并行化/加速并行numba代码?

与命令行相比,相同的Python代码在Companyter Notebook中运行速度慢20倍

在pandas数据框中计算相对体积比指标,并添加指标值作为新列

如何使用使用来自其他列的值的公式更新一个rabrame列?