为什么x ** 3比x * x * x慢?
这个问题在这里已经有了答案:
按照这个答案,这是因为幂运算的实现有一些乘法运算没有的开销。 然而,随着指数的增加,初始乘法会变得越来越慢。 经验证明:
In [3]: x = np.random.rand(1e6)
In [15]: %timeit x**2
100 loops, best of 3: 11.9 ms per loop
In [16]: %timeit x*x
100 loops, best of 3: 12.7 ms per loop
In [17]: %timeit x**3
10 loops, best of 3: 132 ms per loop
In [18]: %timeit x*x*x
10 loops, best of 3: 27.2 ms per loop
In [19]: %timeit x**4
10 loops, best of 3: 132 ms per loop
In [20]: %timeit x*x*x*x
10 loops, best of 3: 42.4 ms per loop
In [21]: %timeit x**10
10 loops, best of 3: 132 ms per loop
In [22]: %timeit x*x*x*x*x*x*x*x*x*x
10 loops, best of 3: 137 ms per loop
In [24]: %timeit x**15
10 loops, best of 3: 132 ms per loop
In [25]: %timeit x*x*x*x*x*x*x*x*x*x*x*x*x*x*x
1 loops, best of 3: 212 ms per loop
请注意指数运算时间保持不变,除了我怀疑是特例的x**2
情况,乘法运算速度越来越慢。 看来你可以利用这个来获得更快的整数求幂...例如:
In [26]: %timeit x**16
10 loops, best of 3: 132 ms per loop
In [27]: %timeit x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x
1 loops, best of 3: 225 ms per loop
In [28]: def tosixteenth(x):
....: x2 = x*x
....: x4 = x2*x2
....: x8 = x4*x4
....: x16 = x8*x8
....: return x16
....:
In [29]: %timeit tosixteenth(x)
10 loops, best of 3: 49.5 ms per loop
看来你可以应用这种技术,一般是将任意整数分成两个幂的和,然后计算两个幂的和,然后求和:
In [93]: %paste
def smartintexp(x, exp):
result = np.ones(len(x))
curexp = np.array(x)
while True:
if exp%2 == 1:
result *= curexp
exp >>= 1
if not exp: break
curexp *= curexp
return result
## -- End pasted text --
In [94]: x
Out[94]:
array([ 0.0163407 , 0.57694587, 0.47336487, ..., 0.70255032,
0.62043303, 0.0796748 ])
In [99]: x**21
Out[99]:
array([ 3.01080670e-38, 9.63466181e-06, 1.51048544e-07, ...,
6.02873388e-04, 4.43193256e-05, 8.46721060e-24])
In [100]: smartintexp(x, 21)
Out[100]:
array([ 3.01080670e-38, 9.63466181e-06, 1.51048544e-07, ...,
6.02873388e-04, 4.43193256e-05, 8.46721060e-24])
In [101]: %timeit x**21
10 loops, best of 3: 132 ms per loop
In [102]: %timeit smartintexp(x, 21)
10 loops, best of 3: 70.7 ms per loop
对于两个小的偶数幂来说,它是快速的:
In [106]: %timeit x**32
10 loops, best of 3: 131 ms per loop
In [107]: %timeit smartintexp(x, 32)
10 loops, best of 3: 57.4 ms per loop
但随着指数变大变慢:
In [97]: %timeit x**63
10 loops, best of 3: 133 ms per loop
In [98]: %timeit smartintexp(x, 63)
10 loops, best of 3: 110 ms per loop
对于大型最坏情况,速度并不快:
In [115]: %timeit x**511
10 loops, best of 3: 135 ms per loop
In [114]: %timeit smartintexp(x, 511)
10 loops, best of 3: 192 ms per loop
作为一个说明,如果你正在计算能力并担心速度:
x = np.random.rand(5e7)
%timeit x*x*x
1 loops, best of 3: 522 ms per loop
%timeit np.einsum('i,i,i->i',x,x,x)
1 loops, best of 3: 288 ms per loop
为什么Einsum更快速仍然是我的一个悬而未决的问题。 虽然它像由于einsum
能够使用SSE2而numpy的的ufuncs不会到1.8。
到位速度更快:
def calc_power(arr):
for x in xrange(arr.shape[0]):
arr[x]=arr[x]*arr[x]*arr[x]
numba_power = autojit(calc_power)
%timeit numba_power(x)
10 loops, best of 3: 51.5 ms per loop
%timeit np.einsum('i,i,i->i',x,x,x,out=x)
10 loops, best of 3: 111 ms per loop
%timeit np.power(x,3,out=x)
1 loops, best of 3: 609 ms per loop
我期望这是因为x**y
必须处理x
和y
都是浮点数的一般情况。 在数学上,我们可以写x**y = exp(y*log(x))
。 遵循你的例子,我发现
x = np.random.rand(1e6)
%timeit x**3
10 loops, best of 3: 178 ms per loop
%timeit np.exp(3*np.log(x))
10 loops, best of 3: 176 ms per loop
我没有检查实际的numpy代码,但它必须在内部做这样的事情。
链接地址: http://www.djcxy.com/p/15021.html