何时在进程上调用 .join()?
问题描述
我正在阅读有关 Python 中的多处理模块的各种教程,但无法理解为什么/何时调用 process.join()
.例如,我偶然发现了这个例子:
I am reading various tutorials on the multiprocessing module in Python, and am having trouble understanding why/when to call process.join()
. For example, I stumbled across this example:
nums = range(100000)
nprocs = 4
def worker(nums, out_q):
""" The worker function, invoked in a process. 'nums' is a
list of numbers to factor. The results are placed in
a dictionary that's pushed to a queue.
"""
outdict = {}
for n in nums:
outdict[n] = factorize_naive(n)
out_q.put(outdict)
# Each process will get 'chunksize' nums and a queue to put his out
# dict into
out_q = Queue()
chunksize = int(math.ceil(len(nums) / float(nprocs)))
procs = []
for i in range(nprocs):
p = multiprocessing.Process(
target=worker,
args=(nums[chunksize * i:chunksize * (i + 1)],
out_q))
procs.append(p)
p.start()
# Collect all results into a single result dict. We know how many dicts
# with results to expect.
resultdict = {}
for i in range(nprocs):
resultdict.update(out_q.get())
# Wait for all worker processes to finish
for p in procs:
p.join()
print resultdict
据我了解,process.join()
会阻塞调用进程,直到调用join方法的进程完成执行.我也相信上面代码示例中启动的子进程在完成目标函数后,即在他们将结果推送到out_q
之后完成执行.最后,我相信 out_q.get()
会阻塞调用过程,直到有结果被提取.因此,如果您考虑代码:
From what I understand, process.join()
will block the calling process until the process whose join method was called has completed execution. I also believe that the child processes which have been started in the above code example complete execution upon completing the target function, that is, after they have pushed their results to the out_q
. Lastly, I believe that out_q.get()
blocks the calling process until there are results to be pulled. Thus, if you consider the code:
resultdict = {}
for i in range(nprocs):
resultdict.update(out_q.get())
# Wait for all worker processes to finish
for p in procs:
p.join()
主进程被 out_q.get()
调用阻塞,直到每个工作进程 完成将其结果推送到队列.因此,当主进程退出 for 循环时,每个子进程都应该已完成执行,对吗?
the main process is blocked by the out_q.get()
calls until every single worker process has finished pushing its results to the queue. Thus, by the time the main process exits the for loop, each child process should have completed execution, correct?
如果是这样的话,此时是否有任何理由调用 p.join()
方法?不是所有的工作进程都已经完成,那么这如何导致主进程等待所有工作进程完成"?我之所以问,主要是因为我在多个不同的示例中看到了这一点,并且我很好奇我是否未能理解某些内容.
If that is the case, is there any reason for calling the p.join()
methods at this point? Haven't all worker processes already finished, so how does that cause the main process to "wait for all worker processes to finish?" I ask mainly because I have seen this in multiple different examples, and I am curious if I have failed to understand something.
解决方案
尝试运行这个:
import math
import time
from multiprocessing import Queue
import multiprocessing
def factorize_naive(n):
factors = []
for div in range(2, int(n**.5)+1):
while not n % div:
factors.append(div)
n //= div
if n != 1:
factors.append(n)
return factors
nums = range(100000)
nprocs = 4
def worker(nums, out_q):
""" The worker function, invoked in a process. 'nums' is a
list of numbers to factor. The results are placed in
a dictionary that's pushed to a queue.
"""
outdict = {}
for n in nums:
outdict[n] = factorize_naive(n)
out_q.put(outdict)
# Each process will get 'chunksize' nums and a queue to put his out
# dict into
out_q = Queue()
chunksize = int(math.ceil(len(nums) / float(nprocs)))
procs = []
for i in range(nprocs):
p = multiprocessing.Process(
target=worker,
args=(nums[chunksize * i:chunksize * (i + 1)],
out_q))
procs.append(p)
p.start()
# Collect all results into a single result dict. We know how many dicts
# with results to expect.
resultdict = {}
for i in range(nprocs):
resultdict.update(out_q.get())
time.sleep(5)
# Wait for all worker processes to finish
for p in procs:
p.join()
print resultdict
time.sleep(15)
然后打开任务管理器.您应该能够看到 4 个子进程在被操作系统终止之前进入僵尸状态几秒钟(由于加入调用):
And open the task-manager. You should be able to see that the 4 subprocesses go in zombie state for some seconds before being terminated by the OS(due to the join calls):
在更复杂的情况下,子进程可能永远处于僵尸状态(就像您在其他 问题),如果你创建了足够多的子进程,你可以填充进程表,导致操作系统出现问题(这可能会杀死你的主进程以避免失败).
With more complex situations the child processes could stay in zombie state forever(like the situation you was asking about in an other question), and if you create enough child-processes you could fill the process table causing troubles to the OS(which may kill your main process to avoid failures).
相关文章