【发布时间】:2017-09-12 08:53:40
【问题描述】:
我试图对两个序列进行纯python(没有外部依赖项)逐元素比较。我的第一个解决方案是:
list(map(operator.eq, seq1, seq2))
然后我从itertools 中找到了starmap 函数,看起来和我很相似。但在最坏的情况下,它在我的电脑上的速度提高了 37%。由于这对我来说并不明显,我测量了从生成器中检索 1 个元素所需的时间(不知道这种方式是否正确):
from operator import eq
from itertools import starmap
seq1 = [1,2,3]*10000
seq2 = [1,2,3]*10000
seq2[-1] = 5
gen1 = map(eq, seq1, seq2))
gen2 = starmap(eq, zip(seq1, seq2))
%timeit -n1000 -r10 next(gen1)
%timeit -n1000 -r10 next(gen2)
271 ns ± 1.26 ns per loop (mean ± std. dev. of 10 runs, 1000 loops each)
208 ns ± 1.72 ns per loop (mean ± std. dev. of 10 runs, 1000 loops each)
在检索元素时,第二种解决方案的性能提高了 24%。之后,它们都为list 产生相同的结果。但是从某个地方我们获得了额外的 13% 时间:
%timeit list(map(eq, seq1, seq2))
%timeit list(starmap(eq, zip(seq1, seq2)))
5.24 ms ± 29.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
3.34 ms ± 84.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
我不知道如何更深入地分析这种嵌套代码?所以我的问题是为什么第一个生成器的检索速度如此之快,并且我们在list 函数中获得了额外的 13%?
编辑:
我的第一个意图是执行逐元素比较而不是all,因此all 函数被替换为list。此替换不影响时序比。
Windows 10(64 位)上的 CPython 3.6.2
【问题讨论】:
-
为什么不直接使用
seq1 == seq2? -
@Błotosmętek 感谢您的指正!我的第一个意图是元素比较而不是
all,这在我的问题中并不明显:) 真的,如果你用list代替all,时间顺序将是相同的。 -
什么 Python 版本?这是 CPython 吗?
-
@MSeifert 是的,Windows 10(64 位)上的 CPython 3.6.2
标签: python performance python-3.x itertools cpython