循环结构中的加速 [英] Speedups in Looping Structures

查看:66
本文介绍了循环结构中的加速的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在以不同方式构建列表时,我注意到一些有趣的行为. .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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆