也许我在做一些奇怪的事情,但是也许在使用numpy时发现了一个令人惊讶的性能损失,不管使用的是什么功率,看起来都是一致的。例如,当x是随机的100x100数组时
x = numpy.power(x,3)
大约比
x = x*x*x
不同阵列大小的加速曲线图显示,阵列大小在10k左右时是一个最佳点,其他大小的阵列的加速速度为5-10倍。
下面要在自己的机器上测试的代码(有点混乱):
import numpy as np
from matplotlib import pyplot as plt
from time import time
ratios = []
sizes = []
for n in np.logspace(1,3,20).astype(int):
a = np.random.randn(n,n)
inline_times = []
for i in range(100):
t = time()
b = a*a*a
inline_times.append(time()-t)
inline_time = np.mean(inline_times)
pow_times = []
for i in range(100):
t = time()
b = np.power(a,3)
pow_times.append(time()-t)
pow_time = np.mean(pow_times)
sizes.append(a.size)
ratios.append(pow_time/inline_time)
plt.plot(sizes,ratios)
plt.title('Performance of inline vs numpy.power')
plt.ylabel('Nx speed-up using inline')
plt.xlabel('Array size')
plt.xscale('log')
plt.show()
有人有解释吗?
众所周知,双倍乘法是非常非常快的,你的处理器可以用一种非常奇特的方式来完成。
pow
明显要慢一些。Some performance guides甚至建议人们对此进行计划,甚至可能在某种程度上有时会有点过分热情。
numpy特殊情况下会进行平方运算,以确保速度不会太慢,但它会将cubing直接发送到libc的
pow
,这几乎没有两个乘法运算快。numpys幂函数的性能与指数呈非线性关系。用天真的方法来比较。无论矩阵大小如何,都应存在相同类型的缩放。基本上,除非指数足够大,否则你不会看到任何实质性的好处。
我怀疑问题是
np.power
总是做浮点求幂,它不知道如何在您的平台(或者,可能是大多数/所有的平台)上优化或矢量化,而乘法很容易被抛到SSE中,即使您不知道,它也相当快即使
np.power
足够聪明,可以分别进行整数幂运算,除非它将小值展开成重复乘法,否则它仍然不会快得多。通过比较int到int、int到float、float到int和float到float的时间,您可以很容易地验证这一点:对于一个小数组,int到int的速度大约是其他数组的5倍,但仍然比乘法慢4倍(尽管我使用PyPy测试了一个定制的NumPy,所以对于具有正常的NumPy安装在CPython上,以提供真正的结果…)
相关问题 更多 >
编程相关推荐