【发布时间】:2017-12-07 02:53:04
【问题描述】:
我正在用 Matlab 编写一个 Python 脚本。碰巧在 Matlab 中,代码运行得更快(比如少了 10 分钟),所以也许你可以帮我弄清楚我做错了什么。我在 Python 中运行了所有会话,发现最慢的是以下两个:
X = xi * math.cos(theta) + zi * (math.sin(theta))
Y = yi
Z = xi * ((-1) * math.sin(theta)) + zi * (math.cos(theta))
x2 = [a * b * c * X[i] / np.sqrt((a * c * Y[i])**2 + b**2 * (
c**2 * (X[i])**2 + a**2 * (Z[i])**2)) for i in range(len(X))]
y2 = [a * b * c * Y[i] / np.sqrt((a * c * Y[i])**2 + b**2 * (
c**2 * X[i]**2 + a**2 * Z[i]**2)) for i in range(len(X))]
zt = c**2 * (1 - (x2 / a)**2 - (y2 / b)**2)
i = 0
z2 = []
for i in range(len(Z)):
z2.append((-1 if Z[i] < 0 else 1) * np.sqrt(zt[i]))
其中 xi,yi 和 zi 是超过 100 万个元素的 numpy 浮点数
谢谢
【问题讨论】:
-
(1) 少 10 分钟并不意味着太多。 1对11; 100 对 110? (2) 做一些真正的分析,也许用 line_profiler。也许包括那个输出 (3) 你真的在那个循环中总结了超过百万个元素吗? (4) 列表追加在复杂性方面是超慢的(edit: 似乎我在这里错了或不准确;但请尝试以下方法)!预分配一个数组。你现在的大小是先验的! (5) 最后一行也可以在numpy中向量化。
-
@sascha:
list.append是摊销常数时间;numpy.append具有可怕的时间复杂度。 -
哎呀...我监督了所有那些隐藏的列表理解。这不是使用 numpy 的方法(避免循环和列表理解;尝试处理完整向量)!阅读一些 numpy 文档。您的代码似乎抛弃了所有 numpy 增益!我不会显示一些代码,也许其他人会。为什么?因为我更喜欢代码,我们也可以复制和运行代码(有时还需要了解您正在做的事情的一些背景知识)!在移植 matlab 代码时,您应该已经可以使用更加矢量化的方法(给定 matlab 代码)。然后read this
-
MATLAB 有很多
jit编译,可以让您定义快速运行的迭代代码。numpy更像是需要“矢量化”整个数组操作的旧 MATLAB。有numpy工具来处理迭代,但首先尝试在没有所有这些列表理解的情况下使其工作。他们很慢。 -
事实上,我在这些列表组合中看不到任何没有开箱即用的矢量化,所以这应该很容易。只需删除方括号、for 语句和所有索引即可。
标签: python performance numpy