我有一个在该州存储大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
电话会议。所以,我的问题是:
Pool
如何在一个班级内工作?究竟是什么腌制?制作了什么副本,以及通过引用传递了什么?) 修改:修改foo
以使用mat
,这更能代表我的真实问题。
答案 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。