我从How can I recover the return value of a function passed to multiprocessing.Process?运行以下解决方案:
import multiprocessing
from os import getpid
def worker(procnum):
print('I am number %d in process %d' % (procnum, getpid()))
return getpid()
if __name__ == '__main__':
pool = multiprocessing.Pool(processes = 3)
print(pool.map(worker, range(5)))
应该输出如下内容:
I am number 0 in process 19139
I am number 1 in process 19138
I am number 2 in process 19140
I am number 3 in process 19139
I am number 4 in process 19140
[19139, 19138, 19140, 19139, 19140]
但我只得到
[4212, 4212, 4212, 4212, 4212]
如果我使用10个以上的进程向pool.map提供1,000,000个范围,我最多看到两个不同的pid。
为什么multiprocessing
的副本似乎在同一个过程中运行所有内容?
答案 0 :(得分:2)
TL; DR :任务没有以任何方式专门分发,也许你的任务很短,所有任务都在其他进程开始之前完成。
通过查看multiprocessing
的来源,似乎任务只是放在Queue
中,工作进程从中读取(函数worker
从Pool._inqueue
读取)。没有计算的分布,工人们正在尽可能地努力工作。
最可能的赌注是,因为任务非常短,所以一个过程在其他人有机会看起来甚至开始之前完成所有这些过程。您可以通过向任务添加两秒sleep
来轻松检查是否是这种情况。
我注意到在我的机器上,任务都非常均匀地分布在流程上(对于#processes> #cores)。因此,似乎存在一些系统依赖性,即使所有进程在工作排队之前都应该有.start()
。
这里有来自worker
的一些修剪来源,它显示每个进程只从队列中读取任务,所以以伪随机顺序:
def worker(inqueue, outqueue, ...):
...
get = inqueue.get
...
while maxtasks is None or (maxtasks and completed < maxtasks):
try:
task = get()
...
SimpleQueue
使用来自Pipe
构造函数的SimpleQueue
进程之间进行通信:
self._reader, self._writer = Pipe(duplex=False)
编辑:可能关于进程启动太慢的部分是错误的,所以我删除了它。在排队任何工作(可能是platform - 依赖)之前,所有进程都是.start()
。我无法在.start()
返回时找到该流程是否准备就绪。