gpt4 book ai didi

python - 为什么我的 Numpy 测试代码比 Matlab 慢 2 倍

转载 作者:太空宇宙 更新时间:2023-11-03 14:24:12 32 4
gpt4 key购买 nike

我一直在用 Python 开发基于菲涅耳系数的反射率求解器,但遇到了一些障碍,因为 Python + Numpy 的性能比 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 代码:

function a = compare_fn(i)

a = rand(1, 400);
vec = rand(1, 400);
tic
for m = 1:i
a = (2.3 + a .* exp(2j*vec))./(1 + (2.3 * a .* exp(2j*vec)));
end
toc

a = compare_fn(200000); Elapsed time is 5.644673 seconds.

我被这个难住了。我已经安装了 MKL(Anaconda 学术许可)。如果有任何帮助确定我的示例中的问题,以及如何使用 Numpy 获得同等甚至更好的性能,我将不胜感激。

一般来说,我无法将循环并行化,因为求解多层的菲涅尔系数涉及递归计算,可以用上述循环的形式表示。

最佳答案

以下内容类似于 unutbu 的已删除答案,对于您的示例输入,我的系统上的运行速度提高了 3 倍。如果您在 Matlab 中像这样实现它,它可能也会运行得更快,但那是另一回事。为了能够使用 ipython 的 %timeit 功能,我将您的原始函数重写为:

def fn(a, vec, i):
for j in xrange(i):
a = (2.3 + a * np.exp(2j*vec))/(1 + (2.3 * a * np.exp(2j*vec)))
return a

我通过从循环中删除指数计算对其进行了优化:

def fn_bis(a, vec, n):
exp_vec = np.exp(2j*vec)
for j in xrange(n):
a = (2.3 + a * exp_vec) / (1 + 2.3 * a * exp_vec)
return a

对这两种方法进行试乘:

In [2]: a = np.random.rand(400)

In [3]: vec = np.random.rand(400)

In [9]: np.allclose(fn(a, vec, 100), fn_bis(a, vec, 100))
Out[9]: True

In [10]: %timeit fn(a, vec, 100)
100 loops, best of 3: 8.43 ms per loop

In [11]: %timeit fn_bis(a, vec, 100)
100 loops, best of 3: 2.57 ms per loop

In [12]: %timeit fn(a, vec, 200000)
1 loops, best of 3: 16.9 s per loop

In [13]: %timeit fn_bis(a, vec, 200000)
1 loops, best of 3: 5.25 s per loop

关于python - 为什么我的 Numpy 测试代码比 Matlab 慢 2 倍,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23073255/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com