【发布时间】:2015-07-11 03:59:23
【问题描述】:
假设您必须使用 2 个甚至 3 个循环来执行计算。直观地说,使用单个循环执行此操作可能会更有效。我尝试了一个简单的 Python 示例:
import itertools
import timeit
def case1(n):
c = 0
for i in range(n):
c += 1
return c
def case2(n):
c = 0
for i in range(n):
for j in range(n):
for k in range(n):
c += 1
return c
print(case1(1000))
print(case2(10))
if __name__ == '__main__':
import timeit
print(timeit.timeit("case1(1000)", setup="from __main__ import case1", number=10000))
print(timeit.timeit("case2(10)", setup="from __main__ import case2", number=10000))
这段代码运行:
$ python3 code.py
1000
1000
0.8281264099932741
1.04944919400441
所以有效地 1 循环似乎更有效。然而,我的问题有一个稍微不同的场景,因为我需要使用数组中的值(在下面的示例中,我使用函数 range 进行简化)。也就是说,如果我将所有内容折叠到一个循环中,我将不得不从另一个数组的值创建一个扩展数组,该数组的大小在 2 到 10 个元素之间。
import itertools
import timeit
def case1(n):
b = [i * j * k for i, j, k in itertools.product(range(n), repeat=3)]
c = 0
for i in range(len(b)):
c += b[i]
return c
def case2(n):
c = 0
for i in range(n):
for j in range(n):
for k in range(n):
c += i*j*k
return c
print(case1(10))
print(case2(10))
if __name__ == '__main__':
import timeit
print(timeit.timeit("case1(10)", setup="from __main__ import case1", number=10000))
print(timeit.timeit("case2(10)", setup="from __main__ import case2", number=10000))
在我的电脑上运行这段代码:
$ python3 code.py
91125
91125
2.435348572995281
1.6435037050105166
所以看起来 3 个嵌套循环更有效,因为我花了一些时间在 case1 中创建数组 b。所以我不确定我是否以最有效的方式创建这个数组,但撇开这个不谈,它真的可以将循环折叠成一个循环吗?我在这里使用 Python,但是像 C++ 这样的编译语言呢?在这种情况下,编译器是否会优化单循环?或者另一方面,当您有多个嵌套循环时,编译器是否会进行一些优化?
【问题讨论】:
-
在第二个示例中,第一个示例是手工制作的有问题的优化,使代码更复杂,更难被编译器和 cpu 优化。此外,它使用更多内存。
-
为什么不
c = sum(i * j * k for i, j, k in itertools.product(range(n), repeat=3))? -
@jonrsharpe 我不能这样做,因为我展示的代码只是为了展示问题。在真正的应用程序中,我在使用该数组结果的循环内做一些其他的事情(线性代数)。
-
@aaragon 所以你想让我们尝试微优化一个看不见的算法?这不太可能很有成效。我建议您实施、测试和分析以找到瓶颈。
-
@jonrsharpe,我的帖子的目的是尝试了解当您处理 1 个或多个循环时真正发生的情况,而不是最终获得优化的代码。我写了一个 Python 示例,直观地向我展示了我的预期。然而,我想知道编译后的代码会发生什么,这个问题对于某些人来说可能太明显了。
标签: python c++ nested-loops interpreted-language compiled-language