Python 在any()语句中迭代一个小列表是否更快?

Python 在any()语句中迭代一个小列表是否更快?,python,list,caching,optimization,iteration,Python,List,Caching,Optimization,Iteration,在长度较短的耐火材料范围内考虑以下操作: d = (3, slice(None, None, None), slice(None, None, None)) In [215]: %timeit any([type(i) == slice for i in d]) 1000000 loops, best of 3: 695 ns per loop In [214]: %timeit any(type(i) == slice for i in d) 1000000 loops, best of

在长度较短的耐火材料范围内考虑以下操作:

d = (3, slice(None, None, None), slice(None, None, None))

In [215]: %timeit any([type(i) == slice for i in d])
1000000 loops, best of 3: 695 ns per loop

In [214]: %timeit any(type(i) == slice for i in d)
1000000 loops, best of 3: 929 ns per loop
设置为
列表
比使用生成器表达式快25%

为什么会出现这种情况,因为设置为
列表
是额外的操作

注意:在两次跑步中,我都得到了警告:
最慢的跑步比最快的跑长6.42倍。这可能意味着正在缓存中间结果
I

分析 在这个特定的测试中,
list()
结构的速度更快,最长可达
4
,从中可以提高生成器的性能

红线显示此事件发生的位置,黑线显示两者性能相同的位置

通过使用所有内核,代码在我的MacBook Pro上运行大约需要1分钟:

import timeit, pylab, multiprocessing
import numpy as np

manager = multiprocessing.Manager()
g = manager.list([])
l = manager.list([])

rng = range(1,16) # list lengths
max_series = [3,slice(None, None, None)]*rng[-1] # alternate array types
series = [max_series[:n] for n in rng]

number, reps = 1000000, 5
def func_l(d):
    l.append(timeit.repeat("any([type(i) == slice for i in {}])".format(d),repeat=reps, number=number))
    print "done List, len:{}".format(len(d))
def func_g(d):
    g.append(timeit.repeat("any(type(i) == slice for i in {})".format(d), repeat=reps, number=number))
    print "done Generator, len:{}".format(len(d))

p = multiprocessing.Pool(processes=min(16,rng[-1])) # optimize for 16 processors
p.map(func_l, series) # pool list
p.map(func_g, series) # pool gens

ratio = np.asarray(g).mean(axis=1) / np.asarray(l).mean(axis=1)
pylab.plot(rng, ratio, label='av. generator time / av. list time')
pylab.title("{} iterations, averaged over {} runs".format(number,reps))
pylab.xlabel("length of iterable")
pylab.ylabel("Time Ratio (Higher is worse)")
pylab.legend()
lt_zero = np.argmax(ratio<1.)
pylab.axhline(y=1, color='k')
pylab.axvline(x=lt_zero+1, color='r')
pylab.ion() ; pylab.show()
import timeit,pylab,多处理
将numpy作为np导入
manager=multiprocessing.manager()
g=经理列表([])
l=管理者列表([])
rng=范围(1,16)#列表长度
max#U系列=[3,切片(无,无,无)]*rng[-1]#备用阵列类型
系列=[max_系列[:n]表示rng中的n]
数量,重复次数=1000000,5
定义功能(d):
l、 追加(timeit.repeat(“any([type(i)==slice for i in{}])。格式(d),repeat=reps,number=number))
打印“完成列表,len:{}”。格式(len(d))
定义函数(d):
g、 append(timeit.repeat(“any(在{}中键入(i)=i的切片)”.format(d),repeat=reps,number=number))
打印“完成生成器,len:{}”。格式(len(d))
p=多处理.Pool(进程=min(16,rng[-1])#针对16个处理器进行优化
p、 地图(功能,系列)#池列表
p、 地图(功能,系列)#泳池发电机
比值=np.asarray(g).平均值(轴=1)/np.asarray(l).平均值(轴=1)
pylab.plot(rng、比率、标签='av.generator time/av.list time')
title(“{}次迭代,在{}次运行上求平均值”。格式(数字,重复次数))
pylab.xlabel(“iterable的长度”)
pylab.ylabel(“时间比率(越高越差)”)
pylab.legend()

lt_zero=np.argmax(比率捕获量是您正在应用的
any
项的大小。在较大的数据集上重复相同的过程:

In [2]: d = ([3] * 1000) + [slice(None, None, None), slice(None, None, None)]*1000

In [3]: %timeit any([type(i) == slice for i in d])
1000 loops, best of 3: 736 µs per loop

In [4]: %timeit any(type(i) == slice for i in d)
1000 loops, best of 3: 285 µs per loop

然后,使用
列表(将所有项加载到内存中)会变得慢得多,生成器表达式的效果也会更好。

我只处理长度不超过10的列表。为什么会出现这种情况?对于长度为10(或者更确切地说,在您的帖子中为3)的列表,元组可以很容易地在计时器的所有迭代中缓存和重用,而生成器版本将始终是惰性的。有没有指向解释此行为的文档的链接/要查找的关键术语?-我应该注意,我尝试搜索了明显的
现金列表迭代
等,但没有获得任何有用的内容检查此:和此:您可以e对更新感兴趣:因此,在这个测试场景中,列表的速度更快,最长可达4个,从中生成程序的速度大大加快!我认为这是非常重要的?显然,向下的选民不同意?问题是否不清楚?为什么问题特别广泛?它对给出的示例不是非常具体?我是向下的选民之一投票者。我否决了它(在任何编辑之前),因为它对我来说似乎缺乏研究。但显然不是。所以+1。@salmanwahed感谢您的反馈,非常感谢我努力在网站上提出体面的问题并提供好的答案