我正在写一个更大的程序,尽快得到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处理这个问题的速度,但是我想更好地编写高效的代码。 有什么办法让这些循环更快的吗?
首先让我注意到,微观速度优化应该在另一种语言中进行。因此,最好使用使用使用c编写功能的库。
关于for循环: 为了加速,展开(小)循环是一种常见的技术,因此让循环来完成任务并不总是更快。通常它只是更通用(而且大多数通用算法实际上比专用算法慢)。
如注释中所述,当用
*
替换-
时,它不会提高python的速度,但是如果涉及的算术操作更少,它可能会提高速度。因此,我将在此处发布计算出的术语:正如你所看到的,有5
+/-
和9*
,在原始版本中有5+/-
和12*
。还要注意,这个版本访问a
只有15次,而原来的版本访问了18次。总结一下,这产生了3个算术运算和3个变量访问小于完全乘法版本。
循环更优雅、更通用,但它们“通常不会比单个表达式中的两个内联乘法更快”。
首先,python中的一个
for
循环必须根据uyou将交互的方式(对range
的调用)来组装对象,然后对循环中的每个项调用迭代器上的一个方法。所以,取决于你在做什么,如果内联表单足够快,你可以保留它-如果它仍然太慢(就像我们在Python中进行数值计算时通常的情况),你应该使用一个数字库(例如NumpY),它可以在本机代码中计算行列式。在这种数字操作代码的情况下,您可以使用本机代码使其运行速度提高数百倍。
如果yo9u需要一些已经生成的库无法执行的数值计算,如果您寻求速度(例如,图像处理中的像素操作),您可能希望编写一个运行在本机代码中的扩展(使用C、Cython或其他东西),以便快速完成它。
另一方面,如果速度不是关键,而且您甚至注意到内联表达式只是“稍微快一点”,那么只需使用完整的循环——您可以获得更可读和可维护的代码——这毕竟是使用Python的主要原因。
在您给出的特定示例中,可以通过对元组的“range”调用进行硬编码来提高循环代码的速度—例如,更改:
for i in range(0, len(a)-2):
到for i in (0, 1, 2)
注意,与内联情况一样,您失去了处理不同大小矩阵的能力。当您展开它时,如上面所建议的,您也可以将两个块合并为一个,因为快速浏览发现两个块之间没有依赖关系(如果我错了,请纠正我)
相关问题 更多 >
编程相关推荐