假設你必須使用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代表itertools.product中的i,j,k(範圍(n),repeat = 3))? – jonrsharpe
@jonrsharpe我不能這樣做,因爲我展示的代碼只是爲了顯示問題。在真正的應用程序中,我使用該數組的結果在循環內部做了一些其他的東西(線性代數)。 – aaragon