小编典典

与通过循环调用函数相比,映射或列表理解实现的性能提升从何而来?

algorithm

我了解到,与执行循环相比,使用内存实现映射的效率更高。但是,我看到使用map函数而不是调用循环迭代的函数也可以提高速度。

这是来自存储位置的一些优化吗?我的意思是,以连续的方式放置内存就是一个例子。我还可以看到,如果这些操作并行运行,那么速度也会有所提高,但我认为情况并非如此。非常欢迎来自任何语言/软件包的地图实现的任何已知优化示例。

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

可能不是完全公平的比较。例如,我测试一个循环实现,列表理解和map函数。您有什么想法可以使一个比另一个更快?不一定需要PYTHON;这更多是关于将功能应用到可迭代对象上的更有效算法的实现的问题。一个有效的答案可能是“通常对于每种映射/列表理解样式的代码,您都可以使循环实现的速度更快”。或者在某些情况下,列表理解速度更快,但这与实现细节有关,这就是我感兴趣的。

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))

输出为:

-------- 6.175041198730469e-05 runtime seconds --------
-------- 5.984306335449219e-05 runtime seconds --------
-------- 5.316734313964844e-05 runtime seconds --------

阅读 278

收藏
2020-07-28

共1个答案

小编典典

因此,在像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")

结果:

Loop: 3.9749317169189453 seconds
Loop-local: 3.686530828475952 seconds
Loop-local-local: 3.006138563156128 seconds
Map: 3.1068732738494873 seconds
Map-local: 3.1318843364715576 seconds
Comprehesion: 2.973804235458374 seconds
Comprehesion-local: 2.7370445728302 seconds

因此,使地图本地化功能并没有真正的帮助,正如我所期望的那样,因为地图在开始时只进行了一次查找。真正令我惊讶的是,对功能局部化的理解和理解之间似乎存在不可忽略的差异。但是,不确定这是否只是噪音。

2020-07-28