【问题标题】:Python, Multiprocessing: what does process.join() do?Python,多处理:process.join() 有什么作用?
【发布时间】:2015-10-01 21:48:54
【问题描述】:
import time
from multiprocessing import Process

def loop(limit):
    for i in xrange(limit):
        pass
    print i

limit = 100000000 #100 million

start = time.time()    

for i in xrange(5):
    p = Process(target=loop, args=(limit,))
    p.start()
p.join()

end = time.time()
print end - start

我尝试运行这段代码,这是我得到的输出

99999999
99999999
2.73401999474
99999999
99999999
99999999

有时

99999999
99999999
3.72434902191
99999999
99999999
99999999
99999999
99999999

在这种情况下,循环函数被调用了 7 次而不是 5 次。为什么会出现这种奇怪的行为?

我也对p.join() 语句的作用感到困惑。它是同时结束任何一个进程还是所有进程?

【问题讨论】:

  • join 不会结束任何事情。它只是一个同步点。它的意思是“我要在这里等到所有流程都完成,然后我们将继续执行”。他们将在完成时完成,无论顺序如何。

标签: python parallel-processing multiprocessing python-multiprocessing


【解决方案1】:

你做事的方式有些问题,试试这个:

start = time.time()    
procs = []
for i in xrange(5):
    p = Process(target=loop, args=(limit,))
    p.start()
    procs.append(p)
[p.join() for p in procs]

问题在于您没有跟踪单个进程(循环内的 p 个变量)。您需要将它们留在身边,以便与它们互动。此更新会将它们保留在数组中,然后在最后加入所有这些。

输出如下所示:

99999999
99999999
99999999
99999999
99999999
6.29328012466

请注意,现在运行的时间也会在执行结束时打印出来。

另外,我运行了您的代码,但无法让循环多次执行。

【讨论】:

    【解决方案2】:

    当前,join 函数将等待您调用的最后一个进程完成,然后再转到下一段代码。如果您浏览您所做的事情,您应该会明白为什么会得到“奇怪”的输出。

    for i in xrange(5):
        p = Process(target=loop, args=(limit,))
        p.start()
    

    这会一个接一个地启动 5 个新进程。这些都在同时运行。 至少,由调度程序决定当前正在处理的进程。

    这意味着您现在有 5 个进程正在运行:

    流程 1

    流程 2

    流程 3

    流程 4

    流程 5

    p.join()
    

    这将等待p 进程完成进程5,因为这是分配给p 的最后一个进程。

    现在让我们说进程 2 首先完成,然后是 进程 5,这是完全可行的,因为调度程序可以让这些进程在 CPU 上占用更多时间。

    流程 1

    进程 2 打印 99999999

    流程 3

    流程 4

    进程 5 打印 99999999

    p.join() 行现在将移动到下一部分,因为 p 进程 5 已完成。

    end = time.time()
    print end - start
    

    此部分打印它的部分,现在有 3 个进程在此输出之后仍在进行。

    其他进程完成并在那里打印 99999999。

    要解决此问题,您需要.join() 所有进程。为此,您可以将代码更改为此...

    processes = []
    
    for i in xrange(5):
        p = Process(target=loop, args=(limit,))
        p.start()
        processes.append(p)
    
    for process in processes:
        process.join()
    

    这将等待第一个进程,然后是第二个,依此类推。一个进程是否在花药之前完成并不重要,因为在脚本继续之前必须等待列表中的每个进程。

    【讨论】:

    • 但为什么有时会运行 7 次?
    • @rfii 因为在这种情况下,如问题中所述,循环被调用了 7 次。 "在这种情况下,循环函数被调用了 7 次而不是 5 次。"
    • 原始问题调用了 5 次,但运行了 7 次。这是原始问题的核心前提。这个答案解释了为什么它可能运行不到 5 次,但不能解释为什么它会运行超过 5 次。我试图理解第二部分。谢谢
    猜你喜欢
    • 1970-01-01
    • 2015-04-06
    • 1970-01-01
    • 2015-10-15
    • 1970-01-01
    • 2014-07-20
    • 2017-09-24
    • 2021-05-01
    • 1970-01-01
    相关资源
    最近更新 更多