假设你在python中有一个列表理解,比如
Values = [ f(x) for x in range( 0, 1000 ) ]
f只是一个没有副作用的函数。所以所有条目都可以独立计算。
与“明显”的实现相比,Python是否能够提高此列表理解的性能;例如通过多核CPU上的共享内存并行化?
答案 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