【问题标题】:Performance discrepancies between itertools.product & list comprehensionitertools.product 和列表理解之间的性能差异
【发布时间】:2020-08-09 18:47:10
【问题描述】:

我在探索 Python 的 itertools 模块时遇到了 itertools.product 函数,它的返回值与 ((x,y) for x in A for y in B) 相同。我发现它是减少复杂for-loops 中的嵌套的一种非常巧妙的方法,其中列表理解可能不足。但是,在继续之前,我想检查它使用替代方法的性能。这是我进行的一些测试。使用 Jupyter Notebook 内置的%%timeit 来衡量性能。

case-1:普通列表理解

%%timeit -n 50 -r 5

[(x,y) for x in range(1000) if x%2==0 for y in range(1000) if y%2==1]
>>> 35.8 ms ± 1.3 ms per loop (mean ± std. dev. of 5 runs, 50 loops each)

case-2:列表理解中的 itertools.product

删除了itertools 导入以避免在此处显示导入时间。

%%timeit -n 50 -r 5

[(x,y) for (x,y) in itertools.product(range(1000), range(1000)) if x%2==0 and y%2==1]
>>> 62.1 ms ± 1.16 ms per loop (mean ± std. dev. of 5 runs, 50 loops each)

case-3:原版嵌套 for 循环

%%timeit -n 50 -r 5

lst = []
for x in range(1000):
    for y in range(1000):
       if x%2 == 0 and y%2 == 1:
           lst.append((x,y))
>>> 72 ms ± 769 µs per loop (mean ± std. dev. of 5 runs, 50 loops each)

case-4:使用 itertools.product 进行 for 循环

%%timeit -n 50 -r 5

lst = []
for x, y in itertools.product(range(1000),range(1000)):
    if x%2==0 and y%2==1:
        lst.append((x,y))
>>> 74.5 ms ± 2.13 ms per loop (mean ± std. dev. of 5 runs, 50 loops each)

但是,我想,this 文档的一部分声称比普通的for 循环具有更好的性能。另外,case-2不应该比case-1快吗?在 case-3case-4 中,itertools.product 的性能差异会随着迭代大小的增加而变差。这里发生了什么?另外,请添加一些示例,其中itertools.product 可能比 listcomp 或嵌套 for 循环更适合。

【问题讨论】:

  • case1 与案例 1 的比较不公平,在案例 1 中,您更早地进行过滤,当不是 x%2==0 时跳过内部循环,因此您不会迭代整个产品。无论如何,我不明白为什么您认为案例 3 和案例 4 应该不同。他们的表现似乎与我所期望的基本相同。
  • 我怀疑itertools.product 的较差性能是由于它创建了它需要的辅助列表,因为它接受任何可迭代,包括迭代器,它们是单通道.

标签: python python-3.x loops functional-programming itertools


【解决方案1】:

你在比较不同的东西:

[(x,y) for x in range(1000) if x%2==0 for y in range(1000) if y%2==1]

...与

不一样
[(x,y) for x in range(1000) for y in range(1000) if x%2==0 and y%2==1]

如果x%2 != 0,第一个完全跳过第二个循环,第二个循环遍历所有1000 ** 2 == 1,000,000 组合。案例 2 到 4 与这里的第二个理解属于同一类别,因此它们本质上比较慢。

【讨论】:

  • 第一个论点很清楚。这两个 listcomps 不一样。错过了%2!=0时的部分。谢谢!但是,case-3case-4 是等价的,对吧?文档说在这种情况下,itertools.product 应该更快,但事实并非如此。
  • @RedowanDelowar 在哪里,确切地在文档中声明了这一点?
  • @RedowanDelowar,是的,它到底是在哪里说的?
  • 上面写着The module standardizes a core set of fast, memory efficient tools that are useful by themselves or in combination. 我想知道它在哪里为您提供了额外的速度?一个例子可能是。
  • @RedowanDelowar,例如,您可以动态创建 itertools' 迭代器,但必须手动编写嵌套循环(您也可以动态创建它们,但更多比使用itertools复杂)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-21
  • 2012-05-26
  • 2013-09-02
  • 2014-03-15
  • 2010-12-07
  • 2017-06-05
相关资源
最近更新 更多