为什么整数指数的numpy.power较慢



我随机选择了这些数字,但这些结果似乎是一致的——浮点指数比整数指数快25%-50%。如何以不同的方式处理这些问题?

In [209]: %timeit -n 100000 -r 100 np.power(3.71242, 7)
100000 loops, best of 100: 3.45 µs per loop
In [210]: %timeit -n 100000 -r 100 np.power(3.71242, 7.0)
100000 loops, best of 100: 1.98 µs per loop

np.power是一个通用函数(ufunc)。这些函数可以用于具有各种不同数据类型的标量和数组,但必须首先检查输入值的类型,以便确定使用哪个内部循环来生成合适的输出值。

如果输入类型没有映射到ufunc的任何预定义循环,则ufunc将尝试将输入值强制转换为合适的类型(除非另有说明)。这种输入值的检查和转换具有相关的性能成本,解释了问题中观察到的时间。

ufunc的types属性显示了输入数据类型将如何映射到输出数据类型。以下是np.power:的映射列表

>>> np.power.types # 'input input -> output'
['bb->b', 'BB->B', 'hh->h', 'HH->H', 'ii->i', 'II->I', 'll->l', 'LL->L', 'qq->q', 
 'QQ->Q', 'ee->e', 'ff->f', 'dd->d', 'gg->g', 'FF->F', 'DD->D', 'GG->G', 'OO->O']

浮点数属于字符代码'g',Python整数属于'l'。这些字符代码的完整列表可以在这里找到。

注意,对于这个ufunc,两个输入值的数据类型必须相同。例如,对于floatint输入数据类型的混合,没有映射。

但我们仍然可以给np.power不同的数据类型,并让它将值强制转换为适当的数据类型。对于floatint,返回float64编号:

>>> np.power(3.71242, 7).dtype
dtype('float64')

在上面,您可以看到映射到float64字符代码g的唯一输入是另外两个g值:'gg->g'

因此,在幕后,np.power(3.71242, 7)采用了Python float和Python int,必须决定可以安全地重铸哪一个以及重铸到什么类型。int值被安全地提升为浮点类型g。然后,ufunc知道要运行哪个循环,并返回另一个g值。

因此,不混合输入数据类型会为np.power带来更好的性能。

最新更新