循环结构中的加速 [英] Speedups in Looping Structures
问题描述
在以不同方式构建列表时,我注意到一些有趣的行为. .append
花费的时间长于列表理解的时间,而列表理解的时间长于map
的时间,如以下实验所示:
I notice some interesting behavior when it comes to building lists in different ways. .append
takes longer than list-comprehensions, which take longer than map
, as shown in the experiments below:
def square(x): return x**2
def appendtime(times=10**6):
answer = []
start = time.clock()
for i in range(times):
answer.append(square(i))
end = time.clock()
return end-start
def comptime(times=10**6):
start = time.clock()
answer = [square(i) for i in range(times)]
end = time.clock()
return end-start
def maptime(times=10**6):
start = time.clock()
answer = map(square, range(times))
end = time.clock()
return end-start
for func in [appendtime, comptime, maptime]:
print("%s: %s" %(func.__name__, func()))
Python 2.7:
Python 2.7:
appendtime: 0.42632
comptime: 0.312877
maptime: 0.232474
Python 3.3.3:
Python 3.3.3:
appendtime: 0.614167
comptime: 0.5506650000000001
maptime: 0.57115
现在,我非常清楚python 2.7中的range
会建立一个列表,因此我明白了为什么python 2.7和3.3中相应功能的时间之间存在差异.我更关心的是append
,列表理解和map
之间的相对时间差.
Now, I am very aware that range
in python 2.7 builds a list, so I get why there is a disparity between the times of the corresponding functions in python 2.7 and 3.3. What I am more concerned about is the relative time differences between append
, list-comprehension and map
.
起初,我认为这可能是因为map
和列表推导可能为解释器提供了最终列表最终大小的知识,这将允许解释器在后台存储足够大的C数组以进行存储.列表.按照这种逻辑,列表理解和map
应该花费几乎相同的时间.
但是,时序数据显示,在python 2.7中,listcomp的速度是append
的〜1.36x,而map
的速度是listcomps的〜1.34x.
更奇怪的是,在python 3.3中,listcomp的速度是append
的1.12倍,而map
实际上比listcomps慢.
At first, I considered that this might be because map
and list comprehensions may afford the interpreter knowledge of the eventual size of the resultant list, which would allow the interpreter to malloc a sufficiently large C array under the hood to store the list. By that logic, list-comprehensions and map
should take pretty much the same amount of time.
However, the timing data shows that in python 2.7, listcomps are ~1.36x as fast as append
, and map
is ~1.34x as fast as listcomps.
More curious is that in python 3.3, listcomps are ~1.12x as fast as append
, and map
is actually slower than listcomps.
很显然,map
和listcomps不会按照相同的规则进行游戏";显然,地图利用了listcomps不会提供的功能.
有人能说明这些计时值之差的原因吗?
Clearly, map
and listcomps don't "play by the same rules"; clearly, map takes advantage of something that listcomps don't.
Could anybody shed some light on the reason behind the difference in these timing values?
推荐答案
首先,在python3.x中,map
返回一个iterable
,而不是列表,因此可以解释那里的50kx加速.为了使其合理,在python3.x中,您需要list(map(...))
.
First, in python3.x, map
returns an iterable
, NOT a list, so that explains the 50kx speedup there. To make it a fair timing, in python3.x you'd need list(map(...))
.
第二,.append
会变慢,因为每次通过循环时,解释器都需要查找列表,然后它需要查找列表中的append
函数.无需在list-comp或map中进行这种额外的.append
查找.
Second, .append
will be slower because each time through the loop, the interpretter needs to look up the list, then it needs to look up the append
function on the list. This additional .append
lookup does not need to happen with the list-comp or map.
最后,通过列表理解,我相信函数square
需要在循环的每一步都进行查找.使用map时,仅在调用map时才查找它,这就是为什么如果要在列表理解中调用一个函数,通常map
会更快.请注意,列表综合通常使用lambda
函数胜过map
.
Finally, with the list-comprehension, I believe the function square
needs to be looked up at every turn of your loop. With map, it is only looked up when you call map which is why if you're calling a function in your list-comprehension, map
will typically be faster. Note that a list-comprehension usually beats out map
with a lambda
function though.
这篇关于循环结构中的加速的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!