我只是重新审视我的一些代码以提高性能,并遇到了一些奇怪的事情:
a = np.linspace(10,1000,1000000).reshape(1000,1000)
%timeit np.square(a)
100 loops, best of 3: 8.07 ms per loop
%timeit a*a
100 loops, best of 3: 8.18 ms per loop
%timeit a**2
100 loops, best of 3: 8.32 ms per loop
好吧,使用幂运算符时似乎有一些开销(**
)但除此之外它们看起来是相同的(我猜 NumPy 就是这么做的),但随后就变得奇怪了:
In [46]: %timeit np.power(a, 2)
10 loops, best of 3: 121 ms per loop
所以没有问题,但为 magic pow 提供后备,而不为 UFUNC 提供后备,似乎有点不一致。但后来我开始感兴趣,因为我经常使用第三次幂:
%timeit a*a*a
100 loops, best of 3: 18.1 ms per loop
%timeit a**3
10 loops, best of 3: 121 ms per loop
%timeit np.power(a, 3)
10 loops, best of 3: 121 ms per loop
第三次幂似乎没有“捷径”,UFUNC 和“magic-pow”的工作原理相同(至少在性能方面)。
但这并不是那么好,因为我想要在代码中使用一致的方法,并且我不太确定如何包装__pow__
的 numpy.
因此,为了切入主题,我的问题是:
有没有办法可以包装 numpys__pow__
方法?因为我想要在我的脚本中以一致的方式写入权力而不是写入a**2
在另一个地方power(a, 3)
。简单地写a**3
,并将其重定向到我的幂函数,将是首选(但为此我需要以某种方式包装 ndarrays__pow__
或者?)。
目前我正在使用快捷方式,但这并不是那么漂亮(我什至必须声明 exponent==2 情况,因为np.power
在那里表现不佳):
def power(array, exponent):
if exponent == 2: #catch this, or it calls the slow np.power(array, exponent)
return np.square(array)
if exponent == 3:
return array * array * array
#As soon as np.cbrt is avaiable catch the exponent 4/3 here too
return np.power(array, exponent)
%timeit power(a, 3)
100 loops, best of 3: 17.8 ms per loop
%timeit a**3
10 loops, best of 3: 121 ms per loop
我正在使用 NumPy v1.9.3 并且我不想子类化np.ndarray
只是为了包裹__pow__
方法。 :-)
编辑:我重写了我提出问题的部分。澄清一下:我并不是在问为什么 NumPy 会这样做——这只是为了解释我为什么问这个问题。