状态为

时间:2017-09-21 03:06:25

标签: python numpy parallel-processing shared-memory python-multiprocessing

我有一个在该州存储大numpy个数组的类。这导致multiprocessing.Pool变得非常慢。这是一个MRE:

from multiprocessing import Pool
import numpy
import time
from tqdm import tqdm

class MP(object):
    def __init__(self, mat):
        self.mat = mat

    def foo(self, x):
        time.sleep(1)
        return x*x + self.mat.shape[0]

    def bar(self, arr):
        results = []
        with Pool() as p:
            for x in tqdm(p.imap(self.foo, arr)):
                results.append(x)
        return results

if __name__ == '__main__':
    x = numpy.arange(8)
    mat = numpy.random.random((1,1))
    h = MP(mat)
    res = h.bar(x)
    print(res)

我在CPU上有4个核心,这意味着这个代码应该(并且确实)在大约2秒内运行。 (tqdm将2秒显示为进度条,此示例并不是必需的)。但是,在主程序中,如果我执行mat = numpy.random.random((10000,10000)),则需要永远运行。我怀疑这是因为Pool正在为每个工作人员制作mat的副本,但我不确定这是如何工作的,因为mat处于类的状态,而不是直接参与imap电话会议。所以,我的问题是:

  1. 为什么会发生这种情况? (即Pool如何在一个班级内工作?究竟是什么腌制?制作了什么副本,以及通过引用传递了什么?)
  2. 这个问题有什么可行的解决方法?
  3. 修改:修改foo以使用mat,这更能代表我的真实问题。

1 个答案:

答案 0 :(得分:0)

如果您说mat没有直接参与imap来电,我猜测MP的状态通常不在imap中使用}调用(如果是,请在下面发表评论,我将删除此答案)。如果是这种情况,则应将foo写为未绑定的函数,而不是MP的方法。立即复制mat的原因是因为foo的每次执行都需要在self中传递,其中包含self.mat

无论mat的大小如何,以下都会快速执行:

from multiprocessing import Pool
import numpy
import time
from tqdm import tqdm


class MP(object):

    def __init__(self, mat):
        self.mat = mat

    def bar(self, arr):
        results = []
        with Pool() as p:
            for x in tqdm(p.imap(foo, arr)):
                results.append(x)
        return results

def foo(x):
    time.sleep(1)
    return x * x

if __name__ == '__main__':
    x = numpy.arange(8)
    mat = numpy.random.random((10000, 10000))
    h = MP(mat)
    res = h.bar(x)
    print(res)

如果foo确实需要传递MP因为它确实需要从mat读取,那么就无法避免向每个处理器发送mat ,你的问题2除了&#34之外没有其他答案;你可以&#t;#34;。但希望我已经回答了你的问题1。