【发布时间】:2021-01-07 08:19:39
【问题描述】:
我正在使用Pool 的工人,并希望他们每个人都使用特定的对象进行初始化。更确切地说,初始化不能并行化,所以我打算在创建worker之前准备好主进程中的对象,并给每个worker一个这些对象。
这是我的尝试:
import multiprocessing
import random
import time
class Foo:
def __init__(self, param):
# NO WAY TO PARALLELIZE THIS !!
print(f"Creating Foo with {param}")
self.param = param
def __call__(self, x):
time.sleep(1)
print("Do the computation", self)
return self.param + str(x)
def initializer():
global myfoo
param = random.choice(["a", "b", "c", "d", "e"])
myfoo = Foo(param)
def compute(x):
return myfoo(x)
multiple_results = []
with multiprocessing.Pool(2, initializer, ()) as pool:
for i in range(1, 10):
work = pool.apply_async(compute, (i,))
multiple_results.append(work)
print([res.get(timeout=2) for res in multiple_results])
这是一个可能的输出:
Creating Foo with b
Creating Foo with a
Do the computation <__main__.Foo object at 0x7f8d70aa7fd0>
Do the computation <__main__.Foo object at 0x7f8d70aa7fd0>
Do the computation <__main__.Foo object at 0x7f8d70aa7fd0>
Do the computation <__main__.Foo object at 0x7f8d70aa7fd0>
Do the computation <__main__.Foo object at 0x7f8d70aa7fd0>
Do the computation <__main__.Foo object at 0x7f8d70aa7fd0>
Do the computation <__main__.Foo object at 0x7f8d70aa7fd0>
Do the computation <__main__.Foo object at 0x7f8d70aa7fd0>
Do the computation <__main__.Foo object at 0x7f8d70aa7fd0>
['b1', 'a2', 'b3', 'a4', 'b5', 'a6', 'b7', 'a8', 'b9']
让我感到困惑的是Foo 对象的地址始终相同,而实际的Foo 对象却不同,从输出中可以看出:"b1", "a2"。
我的问题是对initializer 的两次调用是并行的,而我不想并行构造Foo。
我想要一些神奇的方法add_worker 来做这样的事情:
pool = multiprocessing.Pool()
for i in range(0,2):
foo = Foo()
poo.add_worker(initializer, (foo,))
有什么想法吗?
编辑:我通过在进程内部而不是在文件顶部制作 kera 的 VGGNet 的import 解决了我真正的生活问题。见this answer
出于好奇,我仍然对答案感兴趣。
【问题讨论】:
-
有趣。在 Windows 上,我得到两个单独的地址......也许这与两个系统之间的内存管理差异有关。也许在 Linux 上,地址是每个进程的内存区域,所以你得到相同的地址......
-
这是一个有趣的问题,但我有一个问题。为什么会打扰你?只要结果没问题...
-
@Tomerikoo 因为初始化函数在并行化时没有完成。在我的真实生活环境中, Foo 对象创建了一个 kera.applications.vgg16;也许我应该提出一个具体问题“如何并行化 vgg16”?
-
如果你想在每个工作人员中创建不同的实例,然后在
compute中创建它们 -
@furas 如果您在
compute中创建Foo的新实例,则compute的每次执行都会有一个不同的Foo实例,而不是每个worker。因此,如果您有 10 个调用compute和 2 个工作人员,您将有 10 个不同的Foo实例,而 @Laurent Clasessesns 似乎只需要其中两个(每个工作人员一个)。如果每次执行compute都有一个不同的Foo实例很好,那么您的方法是正确的。
标签: python python-3.x python-multiprocessing