在Python和Matlab中,我编写了代码生成矩阵并通过索引函数填充它。Python代码的执行时间比MATLAB代码的执行时间长约20倍。两个具有相同结果的函数在Python中写下,bWay()
基于此答案
这是完整的Python代码:
import numpy as np
from timeit import timeit
height = 1080
width = 1920
heightCm = 30
distanceCm = 70
centerY = height / 2 - 0.5;
centerX = width / 2 - 0.5;
constPart = height * heightCm / distanceCm
def aWay():
M = np.empty([height, width], dtype=np.float64);
for y in xrange(height):
for x in xrange(width):
M[y, x] = np.arctan(pow((pow((centerX - x), 2) + pow((centerY - y), 2)), 0.5) / constPart)
def bWay():
M = np.frompyfunc(
lambda y, x: np.arctan(pow((pow((centerX - x), 2) + pow((centerY - y), 2)), 0.5) / constPart), 2, 1## Heading ##
).outer(
np.arange(height),
np.arange(width),
).astype(np.float64)
这是完整的MATLAB代码:
height = 1080;
width = 1920;
heightCm = 30;
distanceCm = 70;
centerY = height / 2 + 0.5;
centerX = width / 2 + 0.5;
constPart = height * heightCm / distanceCm;
M = zeros(height, width);
for y = 1 : height
for x = 1 : width
M(y, x) = atan(((centerX - x)^2 + (centerY - y)^2)^0.5 / constPart);
end
end
用TimeIt测量的Python执行时间。TimeIt:
aWay() - 6.34s
bWay() - 6.68s
用抽动TOC测量的MATLAB执行时间:
0.373s
要缩小它,我测量了arctan
,平方和循环时间
python:
>>> timeit('arctan(3)','from numpy import arctan', number = 1000000)
1.3365135641797679
>>> timeit('pow(3, 2)', number = 1000000)
0.11460829719908361
>>> timeit('power(3, 2)','from numpy import power', number = 1000000)
1.5427879383046275
>>> timeit('for x in xrange(10000000): pass', number = 1)
0.18364813832704385
matlab:
tic
for i = 1 : 1000000
atan(3);
end
toc
Elapsed time is 0.179802 seconds.
tic
for i = 1 : 1000000
3^2;
end
toc
Elapsed time is 0.044160 seconds.
tic
for x = 1:10000000
end
toc
Elapsed time is 0.034853 seconds.
在所有三种情况下,Python代码执行时间更长。
我有什么可以做的来改善此Python代码性能?
我只专注于python部分,以及如何优化它(从未使用过matlab,对不起(。
如果我正确理解您的代码,则可以使用:
def fastway():
x, y = np.ogrid[:width, :height] # you may need to swap "x" and "y" here.
return np.arctan(np.hypot(centerX-x, centerY-y) / constPart)
这是矢量化的,应该很快。
%timeit fastway()
# 289 ms ± 9.62 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit aWay()
# 28.2 s ± 243 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit bWay()
# 29.3 s ± 790 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
如果您想知道:np.hypot(x, y)
与(x**2 + y**2)**0.5
相同。它不一定更快,但较短,在某些边缘情况下会提供更精确的结果。
另外,如果您需要在标量上操作,则不应使用numpy函数。Numpy函数的开销很高,以至于处理一个元素所需的时间与处理一千个元素的时间相同,例如,请参见我在" numpy中不同矢量化方法中的性能"问题上的答案。
<</p>使Mseifert的答案完成,这是矢量化MATLAB代码:
height = 1080;
width = 1920;
heightCm = 30;
distanceCm = 70;
centerY = height / 2 + 0.5;
centerX = width / 2 + 0.5;
constPart = height * heightCm / distanceCm;
[x, y] = meshgrid(1:width, 1:height);
M = atan(hypot(centerX-x, centerY-y) / constPart);
在我的机器上,这需要0.057秒,而循环的双重循环需要0.20秒。
在同一台计算机上,Mseifert的Python解决方案需要0.082秒。