gpt4 book ai didi

python - 为什么我的 'xmap' 函数并不比内置的 'map' 快?

转载 作者:太空宇宙 更新时间:2023-11-04 07:01:55 26 4
gpt4 key购买 nike

假设有一个 A 类,并且有一个名为 lst 的 A 类实例列表。

假设我们要对列表中的每个实例一遍又一遍地调用类 A 的特定方法 m 数百万次,(实际示例:entity.游戏循环中的 update() 方法)。我们知道执行此操作的简单方法如下:

for obj in lst: obj.m()

然而,这种代码会让我们昏昏欲睡。于是我们想到使用map的方式如下:

map(lambda obj: obj.m(), lst)

但是我们对上面的代码行进行了几次测试,结果发现它比我们简单的 for 循环要慢得多。有时它甚至慢 2 倍。然后我们自己想,“嗯,它可能更慢,因为 map 为所有函数调用构造了一个返回值列表并返回该列表”。

假设我们从名为 xrange 的惰性且内存高效的内置函数中获得灵感。大多数情况下,我们认为它是 range 的更酷版本。因此,我们定义了一个名为 xmap 的函数,它只是将一个函数应用于一个对象列表,而不构造一个返回值列表并返回它。实现如下:

def xmap(func, lst):
for obj in lst: func(obj)

非常酷,因为这个函数只是执行上面的 for 循环,只是它允许我们保持幻想并发送我们的 lambda 函数。我们认为这是完美的妥协。但是我们一丝不苟,所以我们决定制作 2 个脚本来测试我们代码的速度,看看我们是否真的比 map 快。

我们的第一个脚本将简单地使用 map 并无用地构造一个我们甚至不需要的列表。

script1.py :

class A:
def m(self):
pass

lst = [A() for i in xrange(15)]

import time
start = time.time()

for i in xrange(1000000):
map(lambda obj: obj.m(), lst)

print time.time()-start, 'seconds'

我们的第二个脚本将使用 xmap,我们相信它会更快,因为它不必构造一个包含 15 个返回值的列表 1,000,000 次并返回它.

script2.py

def xmap(func, lst):
for obj in lst: func(obj)

class A:
def m(self):
pass

lst = [A() for i in xrange(15)]

import time
start = time.time()

for i in xrange(1000000):
xmap(lambda obj: obj.m(), lst)

print time.time()-start, 'seconds'

我们终于完成了,很高兴看到我们的代码会快多少。然而,在对彼此运行这两个脚本几次之后,事实证明 script2.py 似乎并不比 script1.py 快。实际上,事实证明,script2.py 有时比 script1.py 运行时间更长。 xmap 似乎与 map 花费的时间差不多。

为什么我会得到这些结果?

C:\dev\py>python script1.py
14.7799999714 seconds

C:\dev\py>python script2.py
14.2170000076 seconds

C:\dev\py>python script1.py
12.1800000668 seconds

C:\dev\py>python script2.py
12.5759999752 seconds

C:\dev\py>python script1.py
14.3020000458 seconds

C:\dev\py>python script2.py
14.9490001202 seconds

C:\dev\py>python script1.py
14.6879999638 seconds

C:\dev\py>python script2.py
14.3139998913 seconds

我认为我至少应该优化 map 中的something 因为我没有构建返回值列表,但我的代码似乎没有快点我知道列表构建需要一些时间,因为我已经完成了以下操作:

>>> import timeit
>>> timeit.timeit('[]')
0.1297345953932106
>>> timeit.timeit('[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]')
0.6807682686160632
>>> timeit.timeit('[None,None,None,None,None,None,None,None,None,None,None,None,
None,None,None]')
0.7460120889200539

那么为什么我的 xmap 函数似乎并不比 map 快?

最佳答案

首先,也是最重要的一点:像这样的时间微优化只会让您感到困惑,因为您正在测量诸如函数之类的非常低级的开销。

不过,在这种情况下,我很确定问题在于,由于额外的 lambda,您可能从 map/xmap 中获得的 yield 正在损失.如果您直接使用 A.m,情况会好很多:

>>> %timeit for obj in lst: obj.m()
100000 loops, best of 3: 2.99 µs per loop
>>> %timeit [obj.m() for obj in lst]
100000 loops, best of 3: 3.5 µs per loop
>>> %timeit xmap(lambda obj: obj.m(), lst)
100000 loops, best of 3: 5.69 µs per loop
>>> %timeit xmap(A.m, lst)
100000 loops, best of 3: 3.32 µs per loop

FWIW,在我看来你的 xmap 最终会获胜:

>>> lst = [A() for i in xrange(10**3)]
>>> %timeit for obj in lst: obj.m()
1000 loops, best of 3: 198 µs per loop
>>> %timeit [obj.m() for obj in lst]
1000 loops, best of 3: 216 µs per loop
>>> %timeit xmap(lambda obj: obj.m(), lst)
1000 loops, best of 3: 353 µs per loop
>>> %timeit xmap(A.m, lst)
10000 loops, best of 3: 189 µs per loop

但我也不会太认真地对待这些数字。

当您说“那种代码 [即简单的 for 循环] 让我们休眠”时,我同意 - 编写简单的循环意味着您可以更快地完成编程并且可以更早上床 sleep 。

关于python - 为什么我的 'xmap' 函数并不比内置的 'map' 快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18994471/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com