Python和列表推导的表现

时间:2011-06-02 11:44:23

标签: python performance list-comprehension

假设你在python中有一个列表理解,比如

Values = [ f(x) for x in range( 0, 1000 ) ]

f只是一个没有副作用的函数。所以所有条目都可以独立计算。

与“明显”的实现相比,Python是否能够提高此列表理解的性能;例如通过多核CPU上的共享内存并行化?

3 个答案:

答案 0 :(得分:8)

不,Python不会为你神奇地并行化。事实上,它不能,因为它不能证明条目的独立性;这需要大量的程序检查/验证,这在一般情况下是不可能的。

如果您想要快速粗粒度多核并行,我建议改为joblib

from joblib import delayed, Parallel
values = Parallel(n_jobs=NUM_CPUS)(delayed(f)(x) for x in range(1000))

我不仅目睹了使用此库的近线性加速,它还具有信号的强大功能,例如从Ctrl-C到其工作进程的信号,这不能说是所有多进程库。

请注意,joblib实际上并不支持共享内存并行性:它会生成工作者进程,而不是线程,因此从向工作程序发送数据并将结果返回到主进程会产生一些通信开销。

答案 1 :(得分:8)

在Python 3.2中,他们添加了concurrent.futures,这是一个可以同时解决问题的好库。考虑这个例子:

import math, time
from concurrent import futures

PRIMES = [112272535095293, 112582705942171, 112272535095293, 115280095190773, 115797848077099, 1099726899285419, 112272535095293, 112582705942171, 112272535095293, 115280095190773, 115797848077099, 1099726899285419]

def is_prime(n):
    if n % 2 == 0:
        return False

    sqrt_n = int(math.floor(math.sqrt(n)))
    for i in range(3, sqrt_n + 1, 2):
        if n % i == 0:
            return False
    return True

def bench(f):
    start = time.time()
    f()
    elapsed = time.time() - start
    print("Completed in {} seconds".format(elapsed))

def concurrent():
    with futures.ProcessPoolExecutor() as executor:
        values = list(executor.map(is_prime, PRIMES))

def listcomp():
    values = [is_prime(x) for x in PRIMES]

我的四核上的结果:

>>> bench(listcomp)
Completed in 14.463825941085815 seconds
>>> bench(concurrent)
Completed in 3.818351984024048 seconds

答案 2 :(得分:0)

尝试以下内容可以更快:

Values = map(f,range(0,1000))

这是代码

的功能方式

另一个想法是用生成器表达式替换代码中的所有出现

imap(f,range(0,1000))  # Python < 3

map(f,range(0,1000))  # Python 3