【问题标题】:multiprocessing slows down my code instead of speeding it up多处理减慢了我的代码而不是加快了它
【发布时间】:2019-07-24 07:20:19
【问题描述】:

我已在许多代码中成功使用multiprocessing.dummy.Pool 来加快循环的计算时间。但是我遇到了一个我无法弄清楚的问题,我添加的线程越多,代码运行的速度就越慢。这一切都在 python 2.7 中,在一个 8 核的 windows 盒子上运行。

import numpy as np
from multiprocessing.dummy import Pool 
from datetime import datetime
global X

pool=Pool(processes=1)

def foo(iy):
    global X
    x=X[iy]
    for i in range(len(x)):
        for j in range(len(x[i])):
            _=np.correlate(x[i,j],[1,1,1],mode='same')
    return None

t=datetime.now()
X=np.random.rand(11,11,512,512)
_=pool.map(foo,range(11))
print((datetime.now()-t).total_seconds())

使用processes=1,运行时间为 0.7 秒。 processes=2 会增加到 1 秒,processes=4 会增加到 2.3 秒。如果我将代码重写如下,也会出现同样的问题:

import numpy as np
from multiprocessing.dummy import Pool 
from datetime import datetime

pool=Pool(processes=1)

def foo(x):
    for i in range(len(x)):
        for j in range(len(x[i])):
            _=np.correlate(x[i,j],[1,1,1],mode='same')
    return None

t=datetime.now()
X=np.random.rand(11,11,512,512)
_=pool.map(lambda z:foo(X[z]),range(11))
print((datetime.now()-t).total_seconds())

我有很多 循环要做,并且真的希望/需要通过将它们拆分为多个内核来加快速度。任何人都知道为什么多处理会减慢我的速度,以及如何解决它?

【问题讨论】:

  • 您确定您不只是针对启动新流程的开销使用有限的数据集进行测试吗?也许用更重的数据集测试它?

标签: python numpy multiprocessing


【解决方案1】:

虽然np.correlate() 可以(在您的情况下可能会)release the GIL,但我认为您的数据太小而无法产生任何好处。也就是说,您的 Python 代码(循环)与 np.correlate() 的“序言”和“尾声”部分(确实持有 GIL)竞争 GIL。

您有几个选项可以提高并行度:

  1. 使用numba.jit(nogil=True) 实现整个计算。但是那里只有 NumPy 的一个子集,我认为不包括 np.correlate()
  2. 使用其他语言(例如 Cython 或 C)实现您的计算,并在计算时释放 GIL。
  3. multiprocessing.dummy(使用线程)切换到multiprocessing(使用进程,因此不存在对 GIL 的争用)。
  4. 在每次调用 np.correlate() 时使用更大的数据。

【讨论】:

  • GIL 仍然是多处理(相对于多线程)的问题吗?不是每个 Python 进程都有自己的内存空间和 GIL 吗?
  • @jmd_dk:是的,正如我在第 3 点中提到的,多处理解决了这个问题,是的,每个进程都有自己的 GIL。
  • 啊,multiprocessing.dummy 实际上并没有使用多处理。明白了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-14
  • 2017-05-20
  • 1970-01-01
  • 1970-01-01
  • 2010-12-22
  • 1970-01-01
相关资源
最近更新 更多