我在Python中开发了一个基于Fresnel系数的反射率求解器,但在Python+numy中的性能比Matlab慢2倍,所以遇到了一些障碍。我将问题代码提炼成一个简单的示例,以显示在每种情况下执行的操作:
测试用例的Python代码:
import numpy as np
import time
def compare_fn(i):
a = np.random.rand(400)
vec = np.random.rand(400)
t = time.time()
for j in xrange(i):
a = (2.3 + a * np.exp(2j*vec))/(1 + (2.3 * a * np.exp(2j*vec)))
print (time.time()-t)
return a
a = compare_fn(200000)
Output: 10.7989997864
等效Matlab代码:
^{pr2}$a = compare_fn(200000); Elapsed time is 5.644673 seconds.
我被这个难住了。我已经安装了MKL(Python学术许可证)。如果有任何帮助,我将非常感谢您通过我的示例来确定问题,以及如何使用Numpy实现同等的性能(如果不是更好的话)。在
一般来说,我不能并行化循环,因为求解多层膜的菲涅耳系数涉及递归计算,可以用上面的循环形式表示。在
下面的内容类似于unutbu的已删除答案,对于您的示例输入,在我的系统上运行速度快3倍。如果像这样在Matlab中实现它,它可能也会运行得更快,但这是另一回事。为了能够使用ipython的
%timeit
功能,我将您的原始函数重写为:我通过从循环中删除指数计算对其进行了优化:
^{pr2}$采用两种方法进行试驾:
我不知道numpypy对你现在所做的是否足够,但你可以试试。在
http://buildbot.pypy.org/numpy-status/latest.html
我已经做了大量的实验,试图确定Matlab和Python/Numpy之间速度差异的来源。一些主要发现是:
Matlab现在有了一个JIT编译器,它在涉及循环的情况下提供了显著的好处。关闭它会将性能降低2倍,使其速度与本机Python+numy代码相似。在
功能加速关闭
a=比较(200000)
运行时间为9.098062秒。
然后我开始使用Numba和Cython探索优化示例函数的选项,看看我能做得更好。对我来说,一个重要的发现是,显式循环计算上的Numba JIT优化比Numpy数组上的本机向量化数学操作更快。我不太明白为什么会这样,但我已经在下面列出了我的示例代码和测试时间。我也和赛顿一起玩过(我不是专家),虽然速度也更快,但Numba还是比Cython快2倍,所以我最终还是和Numba一起参加了测试。
这是3个等价函数的代码。第一个是Numba优化函数,它有一个显式循环来执行元素计算。第二个函数是Python+Numpy函数,它依赖于Numpy向量化来执行计算。第三个函数尝试使用Numba来优化矢量化的Numpy代码(但是没有改进,正如您在结果中看到的那样)。最后,我包含了Cython代码,尽管我只测试了一个案例。在
计时结果:
i.单个外循环的计时-演示矢量化计算的效率
二。在短数组上计算大循环的极端情况下的计时(预计Numpy+Python的性能较差)
iii.测试上述两种情况之间的中间位置
正如您所看到的,使用Numba可以提高效率1.5X-30X的系数。与Cython相比,它的高效性和易用性给我留下了深刻的印象。在
相关问题 更多 >
编程相关推荐