问题 Python itertools - 慢?


我正在尝试使用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)

11007
2018-02-17 23:09


起源

“我错过了什么吗?” - 你似乎缺少的是没有人声称这个想法 itertools.product() 是加速嵌套的循环 - - Sven Marnach
@Sven Marnach 9.7。 itertools - 为高效循环创建迭代器的函数...docs.python.org/library/itertools.html - Robert William Hanks


答案:


看起来确实如此 itertools.product 对于较大的值较慢 n

在[24]中:打印_23
来自itertools导入产品

def nested_loops(n):
    对于范围内的i(n):
        对于范围内的j(n):
            对于范围内的k(n):
                通过

def itertools_product(n):
    对于产品中的(i,j,k)(范围(n),重复= 3):
        通过


在[25]中:%timeit nested_loops(128)
10个循环,最佳3:每循环68.6毫秒

在[26]中:%timeit itertools_product(128)
10个循环,每个循环最好为3:162 ms

在[27]中:%timeit nested_loops(10)
10000循环,最佳3:每循环84.5 us

在[28]中:%timeit itertools_product(10)
10000循环,最佳3:每循环79.8 us

在[30]中:%timeit nested_loops(300)
1个循环,最佳3:833 ms每个循环

在[31]中:%timeit itertools_product(300)
1个循环,最佳3:每循环2.07秒

没有元组拆包:

在[40]中:print _39
来自itertools导入产品

def itertools_product(n):
    对于产品中的ijk(范围(n),重复= 3):
        通过

在[41]中:%timeit itertools_product(128)
10个循环,最佳3:115 ms每循环

在[42]中:%timeit itertools_product(10)
10000循环,最佳3:每循环59.2 us

在[43]中:%timeit itertools_product(300)
1个循环,最好为3:每循环1.47秒

此外,为了好玩,列表推导和生成器表达式:

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

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

在[51]中:%timeit list_comprehension_product(128)
1个循环,每个循环最好为3:583 ms

在[52]中:%timeit generator_expression_product(128)
1个循环,最佳3:480 ms每个循环

这些基准测试是在 python --version

2.6.7(r267:88850,2011年7月31日,19:30:54)
[GCC 4.2.1(基于Apple Inc. build 5658)(LLVM build 2335.15.00)]

9
2018-02-17 23:15



是的,对于大范围来说似乎更慢。这正是你希望它更快的地方 - 对吗? - repoman


似乎第二个循环比第一个循环慢,可能是因为元组解包。你不必这样做,我发现它使第二个循环更快,像这样:

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

当然,使用numpy,你想要避免循环遍历元素,而是立即对整个数组使用numpy操作。这样,所有循环等都在C中完成,你将获得巨大的加速。


5
2018-02-17 23:16



不希望这个与numpy相关。只是使用numpy来获得允许快速三重索引的东西。本来可以通过三个参数调用某个函数... - repoman