与通过循环调用函数相比,map或list理解实现的性能提升来自何处?

2024-09-29 00:22:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道在map的实现中使用内存比在循环中实现内存更有效。但是,我发现使用map函数而不是调用循环上迭代的函数也可以提高速度。在

这是不是源于存储内存的优化?我所说的一个例子是内存的放置方式是连续的。我还可以看出,如果操作是并行运行的,那么速度也会提高,但我不认为是这样。欢迎从任何语言/包中的任何已知的映射实现优化示例!在

——编辑:我觉得以前的例子并不能很好地说明我的问题。在

比较起来可能并不完全公平。 例如,我测试a循环实现、列表理解和map函数。你知道怎样才能使一个比另一个快吗?不一定是PYTHON;这更多的是关于如何实现更有效的算法来将函数应用于iterable对象的问题。一个有效的答案可能是“通常对于每一种map/list理解风格的代码,您将能够更快地实现一个循环”。或者在某些情况下,列表理解更快,但这与实现细节有关,这正是我感兴趣的。在

import time
import numpy as np


def square2(x):
return x*x


def main():
    foobar = np.linspace(1, 300, 300)

    start_time = time.time()
    res = [0] * len(foobar)
    for i, foo in enumerate(foobar):
        res[i] = square2(foo)
    print("{} {} runtime seconds {}".format("-"*8, time.time()-start_time, "-"*8))

    res = [0] * len(foobar)
    start_time = time.time()
    res = [square2(foo) for foo in foobar]
    print("{} {} runtime seconds {}".format("-"*8, time.time()-start_time, "-"*8))

    start_time = time.time()
    res = list(map(square2, foobar))
    print("{} {} runtime seconds {}".format("-"*8, time.time()-start_time, "-"*8))

输出为:

^{pr2}$

Tags: 函数内存formatmapfootimeresstart
2条回答

因此,在Python这样的动态语言中,循环中函数调用的问题是,解释器每次都要评估引用,而且代价很高,特别是对于全局变量。但是,请注意,当您将内容设为本地时会发生什么:

import time
def square(x):
    return x*x

def test_loop(x):
    res = []
    for i in x:
        res.append(square(i))
    return res


def test_map(x):
    return  list(map(square,x))

def test_map_local(x, square=square):
    return  list(map(square,x))


def test_loop_local(x, square=square):
    res = []
    for i in x:
        res.append(square(i))
    return res

def test_loop_local_local(x, square=square):
    res = []
    append = res.append
    for i in x:
        append(square(i))
    return res

def test_comprehension(x):
    return [square(i) for i in x]

def test_comprehension_local(x, square=square):
    return [square(i) for i in x]

x = range(1,10000000)

start = time.time()
test_loop(x)
stop = time.time()
print("Loop:", stop - start,"seconds")

start = time.time()
test_loop_local(x)
stop = time.time()
print("Loop-local:", stop - start, "seconds")

start = time.time()
test_loop_local_local(x)
stop = time.time()
print("Loop-local-local:", stop - start, "seconds")

start = time.time()
test_map(x)
stop = time.time()
print("Map:", stop - start, "seconds")

start = time.time()
test_map_local(x)
stop = time.time()
print("Map-local:", stop - start, "seconds")

start = time.time()
test_comprehension(x)
stop = time.time()
print("Comprehesion:", stop - start, "seconds")

start = time.time()
test_comprehension_local(x)
stop = time.time()
print("Comprehesion-local:", stop - start, "seconds")

结果:

^{pr2}$

所以,让函数在map local中查找并没有真正的帮助,正如我所期望的那样,因为map在一开始只进行一次查找。真正让我吃惊的是,理解和理解之间似乎有一个不可忽视的区别。不过,不确定这是否只是噪音。在

差异是由于追加,而不是映射。试试这个:

res = []
res = [square2(foo) for foo in foobar]

相关问题 更多 >