Python多处理疑难解答

Python多处理疑难解答,python,macos,python-3.x,multiprocessing,Python,Macos,Python 3.x,Multiprocessing,最近我想用并行处理来加速我的一些代码,因为我有一个四核i7,这看起来像是浪费。我了解了python的GIL(如果需要的话,我将使用V3.3.2),以及如何使用多处理模块克服它,因此我编写了以下简单的测试程序: from multiprocessing import Process, Queue def sum(a,b): su=0 for i in range(a,b): su+=i q.put(su) q= Queue() p1=Process(t

最近我想用并行处理来加速我的一些代码,因为我有一个四核i7,这看起来像是浪费。我了解了python的GIL(如果需要的话,我将使用V3.3.2),以及如何使用多处理模块克服它,因此我编写了以下简单的测试程序:

from multiprocessing import Process, Queue

def sum(a,b):
    su=0
    for i in range(a,b):
        su+=i
    q.put(su)

q= Queue()

p1=Process(target=sum, args=(1,25*10**7))
p2=Process(target=sum, args=(25*10**7,5*10**8))
p3=Process(target=sum, args=(5*10**8,75*10**7))
p4=Process(target=sum, args=(75*10**7,10**9))

p1.run()
p2.run()
p3.run()
p4.run()

r1=q.get()
r2=q.get()
r3=q.get()
r4=q.get()

print(r1+r2+r3+r4)
使用cProfile测得的代码运行时间约为48秒,但是单进程代码

def sum(a,b):
    su=0
    for i in range(a,b):
        su+=i
    print(su)

sum(1,10**9)

大约50秒后运行。我知道这种方法会带来间接费用,但我预计改进会更大。with fork()不适用于我的,因为我正在Mac上运行代码。

问题是您调用的是
run
,而不是
start

如果您阅读文档,则是“表示流程活动的方法”,而是在后台流程上启动流程活动的函数。(这与
线程相同。线程

因此,您要做的是在主进程上运行
sum
函数,而从不在后台进程上执行任何操作


从我的笔记本电脑上的计时测试来看,这将时间缩短到原来的37%。不是你希望的25%,我也不知道为什么,但是…足以证明它是真正的多处理。(事实上,我得到了四个额外的
Python
进程,每个进程都使用60-100%的CPU…

如果你真的想用Python编写快速计算,那就不是办法。使用numpy或cython。您的计算速度将是普通python的一百倍

另一方面,如果您只想启动一堆parralel作业,请使用适当的工具,例如

from multiprocessing import Pool

def mysum(a,b):
    su=0
    for i in range(a,b):
    su+=i
    return su

with Pool() as pool:
    print(sum(pool.starmap(mysum, ((1,25*10**7), 
                               (25*10**7,5*10**8),
                               (5*10**7,75*10**7),
                               (75*10**7,10**9)))))

在并行运行期间,您是否观察了CPU负载?是否加载了多个核心?是的,所有4个核心中的活动都出现峰值,奇怪的是,在顺序案例中也发生了相同的情况。Activity monitor还声称python只使用了1个线程,在计算过程的一半左右切换到2个线程(在并行情况下)
multiprocessing
启动单独的进程,这些进程在Activity monitor中获得单独的行(通常都称为“python”)。此外,值得注意的是,对于这样的代码,使用
多处理.Pool
并发.futures.ProcessPoolExecutor
通常比使用显式
进程
es和
队列
s更容易。例如,比较一下。哇,下降到20秒,不完全是4x in所希望的,但无论如何都很受欢迎D@Michal:看起来我在同一时间运行了与您相同的测试,得到了几乎相同的结果(37%对40%)。我有点好奇到底发生了什么(在大部分工作中绝对没有争用,使用的内存很少,…),但还不足以深入研究。您的示例实际上没有返回值,因此无法在最后打印出来。请参阅,以获取相关代码(并干净地关闭池)。您的方法更好;)另一方面,您最初的方式将更容易适应
imap_unordered
(在这种情况下,这可能是值得的,如果我们所做的只是添加它们,那么就没有理由按顺序获取结果),因为没有
istarmap_unordered