2012-02-17 66 views
11

我正在嘗試使用Python的itertools模塊來加速三重嵌套for循環。下面的測試碼進行比較以itertools'產品的方法,並輸出一個標準的三重嵌套循環:Python的itertools - 慢?

嵌套循環時間= 2.35023秒

Itertools循環時間= 2.67766秒

我缺少的東西?

import numpy 
import itertools 
import time 

n = 128 
a = numpy.arange(n**3).reshape((n,n,n)) 
b = numpy.zeros((n,n,n)) 
c = numpy.zeros((n,n,n)) 

t = time.time() 
for i in range(n): 
    for j in range(n): 
     for k in range(n): 
      b[i,j,k] = a[i,j,k] 
print 'Nested loop time = %g secs' % (time.time() - t) 

t = time.time() 
for (i,j,k) in itertools.product(range(n), repeat=3): 
    c[i,j,k] = a[i,j,k] 
print 'Itertools loop time = %g secs' % (time.time() - t) 
+0

「我錯過了什麼嗎?」 - 你似乎缺少的是沒有人聲稱'itertools.product()'的想法是加速嵌套循環 - – 2012-02-19 03:14:33

+3

@Sven Marnach 9.7。 itertools - 爲高效循環創建迭代器的函數... http://docs.python.org/library/itertools.html – 2012-02-20 01:56:54

回答

9

它似乎像itertools.product是的n大值慢:

 
In [24]: print _23 
from itertools import product 

def nested_loops(n): 
    for i in range(n): 
     for j in range(n): 
      for k in range(n): 
       pass 

def itertools_product(n): 
    for (i,j,k) in product(range(n), repeat=3): 
     pass 


In [25]: %timeit nested_loops(128) 
10 loops, best of 3: 68.6 ms per loop 

In [26]: %timeit itertools_product(128) 
10 loops, best of 3: 162 ms per loop 

In [27]: %timeit nested_loops(10) 
10000 loops, best of 3: 84.5 us per loop 

In [28]: %timeit itertools_product(10) 
10000 loops, best of 3: 79.8 us per loop 

In [30]: %timeit nested_loops(300) 
1 loops, best of 3: 833 ms per loop 

In [31]: %timeit itertools_product(300) 
1 loops, best of 3: 2.07 s per loop 

而且沒有元組拆包:

 
In [40]: print _39 
from itertools import product 

def itertools_product(n): 
    for ijk in product(range(n), repeat=3): 
     pass 

In [41]: %timeit itertools_product(128) 
10 loops, best of 3: 115 ms per loop 

In [42]: %timeit itertools_product(10) 
10000 loops, best of 3: 59.2 us per loop 

In [43]: %timeit itertools_product(300) 
1 loops, best of 3: 1.47 s per loop 

此外,爲了好玩,列表內涵和發電機表達式:

 
def list_comprehension_product(n): 
    range_n = range(n) 
    for (i,j,k) in [ (i, j, k) for i in range_n for j in range_n for k in range_n ]: 
     pass 

def generator_expression_product(n): 
    range_n = range(n) 
    for (i,j,k) in ((i, j, k) for i in range_n for j in range_n for k in range_n): 
     pass 

In [51]: %timeit list_comprehension_product(128) 
1 loops, best of 3: 583 ms per loop 

In [52]: %timeit generator_expression_product(128) 
1 loops, best of 3: 480 ms per loop 

這些基準測試與python --version運行:

2.6.7 (r267:88850, Jul 31 2011, 19:30:54) 
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)]
+1

是的,它對於大範圍似乎確實比較慢。這正是你希望它更快的地方 - 對嗎? – repoman 2012-02-17 23:50:23

5

它似乎是第二個循環是也許是因爲元組拆包比第一速度較慢。你沒有做到這一點,我覺得它使第二循環更快地做到這一點是這樣的:

for ijk in itertools.product(range(n), repeat=3): 
    c[ijk] = a[ijk] 

當然,與numpy的,你要避免遍歷所有的元素,而是使用立即對整個陣列進行numpy操作。這樣,所有的循環等,都在C中完成,而且你會得到巨大的加速。

+0

不希望這是numpy相關。只是使用numpy有一些可以實現快速三重索引的功能。可能是一個三重參數的函數調用... – repoman 2012-02-17 23:49:03