首页 > 解决方案 > 如何在 Python 中同时发生两件不同的事情?

问题描述

我习惯了多处理,但现在我有一个问题mp.Pool,我需要的工具不是。

我有一个准备输入的进程和另一个使用它的进程。我并没有用完我所有的内核,所以我想让两个内核同时运行,第一个内核为下一次迭代做好准备。我该怎么做呢?并且(重要的是)这种东西叫什么,以便我可以去谷歌搜索它?

这是一个虚拟示例。以下代码需要 8 秒:

import time
def make_input():
    time.sleep(1)
    return "cthulhu r'lyeh wgah'nagl fhtagn"

def make_output(input):
    time.sleep(1)
    return input.upper()

start = time.time()
for i in range(4):
    input = make_input()
    output = make_output(input)
    print(output)

print(time.time() - start)

CTHULHU R'LYEH WGAH'NAGL FHTAGN
CTHULHU R'LYEH WGAH'NAGL FHTAGN
CTHULHU R'LYEH WGAH'NAGL FHTAGN
CTHULHU R'LYEH WGAH'NAGL FHTAGN
8.018263101577759

如果我在进行输出的同时准备输入批次,则需要四秒钟。像这样的东西:

next_input = make_input()
start = time.time()
for i in range(4):
    res = do_at_the_same_time(
        output = make_output(next_input),
        next_input = make_input()
    )
    print(output)

print(time.time() - start)

但是,显然,这是行不通的。我怎样才能完成我想要完成的事情?

重要说明:我尝试了以下操作,但失败了,因为执行工作人员在错误的范围内工作(例如,对于我的实际用例)。在我的虚拟用例中,它不起作用,因为它在不同的进程中打印。

def proc(i):
    if i == 0:
        return make_input()
    if i == 1:
        return make_output(next_input)

next_input = make_input()
for i in range(4):
    pool = mp.Pool(2)
    next_input = pool.map(proc, [0, 1])[0]
    pool.close()

所以我需要一个解决方案,其中第二个进程发生在与 for 循环相同的范围或环境中,并且第一个进程具有可以从该范围获得的输出。

标签: pythonconcurrencyparallel-processing

解决方案


您应该可以使用Pool. 如果我理解正确,您希望一个工作人员为下一个工作人员准备输入,该工作人员运行并使用它做更多事情,给定您的示例函数,这应该这样做:

pool = mp.Pool(2)
for i in range(4):
    next_input = pool.apply(make_input)
    pool.apply_async(make_output, (next_input, ), callback=print)
pool.close()
pool.join()

我们准备了一个包含 2 个工作人员的池,现在我们要运行循环以两次运行我们的这对任务。

我们make_input使用apply()等待函数完成将结果分配给工作人员委托给next_input. 注意:在此示例中,我们可以使用单个工作池并运行next_input = make_input()(即在您的脚本运行的同一进程中并仅委托make_output())。

现在更有趣的一点:通过使用apply_async()我们要求一个工人运行make_output,将单个参数传递next_input给它并告诉它runt(或任何函数)print,并将结果make_output作为参数传递给注册的函数callback

然后我们close()池不再接受任何工作并join()等待进程完成它们的工作。


推荐阅读