【问题标题】:How do I make two different things happen at the same time in Python?如何在 Python 中同时发生两件不同的事情?
【发布时间】:2020-03-05 22:53:52
【问题描述】:

我习惯了多处理,但现在我遇到了一个问题,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 循环相同的范围或环境中,并且第一个进程具有可以从该范围获得的输出。

【问题讨论】:

  • 听起来你可能正在寻找进程间通信。
  • 特别是在 CPython(普通解释器)中,为什么你的两个函数需要相当长的时间来执行是非常重要的。您是否可以在两个单独的(如果相关)脚本中进行这两种处理也很重要。因此,请告诉我们更多信息(也许可以代替您的 Pool 示例,这实际上并不那么重要)。

标签: python concurrency parallel-processing


【解决方案1】:

您应该可以使用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 个 worker 的池,现在我们想要运行循环来运行我们的两个任务。

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

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

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

【讨论】:

    猜你喜欢
    • 2016-05-08
    • 1970-01-01
    • 1970-01-01
    • 2011-10-29
    • 2017-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多