我正在编写一个更大的程序,尽快获得3x3矩阵的决定因素对于它运行良好非常重要。我已经读过我可以使用numPy来做这件事,但我认为编写自己的代码可能会更有教育意义,因为我在CompSci的第三学期。
所以我编写了两个函数,我正在使用time.clock()(我在win7机器上)来计算每个函数返回值所需的时间。
这是第一个功能:
def dete(a):
x = (a[0][0] * a[1][1] * a[2][2]) + (a[1][0] * a[2][1] * a[3][2]) + (a[2][0] * a[3][1] * a[4][2])
y = (a[0][2] * a[1][1] * a[2][0]) + (a[1][2] * a[2][1] * a[3][0]) + (a[2][2] * a[3][1] * a[4][0])
return x - y
这是第二个功能:
def det(a):
a.append(a[0]); a.append(a[1]);
x = 0
for i in range(0, len(a)-2):
y=1;
for j in range(0, len(a)-2):
y *= a[i+j][j]
x += y
p = 0
for i in range(0, len(a)-2):
y=1;
z = 0;
for j in range(2, -1, -1):
y *= a[i+z][j]
z+=1
z += 1
p += y
return x - p
他们都给出了正确的答案,但是第一个似乎稍快一点,这让我觉得因为for循环使用起来更优雅,而且通常更快,我做错了 - 我做了循环慢而肥。我尝试将其修剪下来,但似乎* =和+ =操作花费了太多时间,其中有太多。 我还没有检查过numPy解决这个问题的速度有多快,但是我想要更好地编写高效的代码。 关于如何使这些循环更快的任何想法?
答案 0 :(得分:3)
首先请注意,微尺度速度优化应该用另一种语言进行。所以你最好使用一个采用c语言功能的库。
关于你的for循环: 为了加速而展开(小)循环是一种常见的技术,因此让循环完成工作并不总是更快。通常它只是更通用(并且大多数通用算法实际上比专用算法慢)。
如评论中所述,当用-
替换*
时,它不会提高python的速度,但如果涉及的算术运算较少,则可能会提高速度。因此,我将在这里发布一个考虑因素的术语:
def dete(a):
return (a[0][0] * (a[1][1] * a[2][2] - a[2][1] * a[1][2])
-a[1][0] * (a[0][1] * a[2][2] - a[2][1] * a[0][2])
+a[2][0] * (a[0][1] * a[1][2] - a[1][1] * a[0][2]))
正如您所看到的那样,有5 +/-
和9 *
与原始版本中有5 +/-
和12 *
。另请注意,此版本只访问a
15次,原始访问次数为18次。
总结这会产生3个算术运算和3个变量访问,小于完全相乘的版本。
答案 1 :(得分:3)
循环 - 更优雅,更通用,但它们并不比单个表达式中的几个内联乘法“通常更快”。
首先,python中的for
循环必须将对象组装在你将要交互的对象上(对range
的调用),然后在该迭代器上为循环上的每个项调用一个方法
所以,根据你在做什么,如果内联形式足够快你保持它 - 如果它仍然太慢(通常是我们在Python中进行数值计算的情况),你应该使用数字库(例如NumpY),可以计算本机代码中的决定因素。对于像这样的数字操作代码,你可以使用本机代码运行数百倍。
如果yo9u需要一些无法通过已经创建的库执行的数值计算,如果您寻求速度(例如,对于图像处理中的像素处理),您可能更喜欢编写以本机代码运行的扩展(使用C,Cython或其他东西)以使其快速。
另一方面,如果速度并不重要,你甚至注意到内联表达式只是“稍微快一点”,只需使用完整循环 - 你可以获得更易读和可维护的代码 - 这是使用Python的主要原因毕竟。
在您给出的具体示例中,您可以通过硬编码对元组的“范围”调用来提高循环代码的速度 - 例如,更改:
for i in range(0, len(a)-2):
到for i in (0, 1, 2)
- 请注意,在内联案例中,您无法使用不同大小的矩阵。
答案 2 :(得分:1)
当您展开它时,如上所述,您也可以将两个块合并为一个,快速浏览一下,发现两个块之间没有依赖关系(如果我错了,请纠正我)
答案 3 :(得分:1)
循环几乎不可能比显式的长表达式更快,所以难怪第一个变量更快。我怀疑你能比第一个功能更快地提出smt。
答案 4 :(得分:0)
你可以展开循环,并利用你处理3x3矩阵而不是nxn矩阵的事实。
通过此优化,您可以摆脱矩阵大小的确定。您可以稍微加快交易灵活性。您可以简单地记下结果矩阵的每个单元格的具体公式。 BTW:(c ++)编译器做了这样的优化。
我只建议这样做,如果你确定这么小的优化值得专门的代码。为了确保您优化代码的正确部分,请使用例如分析工具请参阅http://docs.python.org/library/profile.html或 timeit 。