我试图使用Python的itertools模块来加速三重嵌套for循环.下面的测试代码将标准的三重嵌套循环与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)
Run Code Online (Sandbox Code Playgroud)
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)]
似乎第二个循环比第一个循环慢,可能是因为元组解包.你不必这样做,我发现它使第二个循环更快,像这样:
for ijk in itertools.product(range(n), repeat=3):
c[ijk] = a[ijk]
Run Code Online (Sandbox Code Playgroud)
当然,对于numpy,你想要避免循环遍历元素,而是立即对整个数组使用numpy操作.这样,所有循环等都在C中完成,你将获得巨大的加速.