我应该在这里使用协程或其他调度对象吗?

时间:2011-04-18 21:15:59

标签: multithreading python-3.x parallel-processing generator coroutine

我目前有一个生成器形式的代码,它调用IO绑定任务。生成器实际上也调用了子生成器,因此可以理解更通用的解决方案。

如下所示:

def processed_values(list_of_io_tasks):
    for task in list_of_io_tasks:
        value = slow_io_call(task)
        yield postprocess(value) # in real version, would iterate over 
                                 # processed_values2(value) here

我完全控制slow_io_call,我不关心从processed_values获取项目的顺序。有没有像coroutines这样的东西可以通过将slow_io_call转换为异步函数并使用哪个调用返回最快来以最快的顺序获得结果?我希望list_of_io_tasks至少有数千个条目。除了使用显式线程之外,我从未做过任何并行工作,特别是我从未使用过各种形式的轻量级线程。

我需要使用标准的CPython实现,而我正在Linux上运行。

1 个答案:

答案 0 :(得分:2)

听起来您正在寻找multiprocessing.Pool(),特别是Pool.imap_unordered()方法。

这是函数的一个端口,它使用imap_unordered()来并行化对slow_io_call()的调用。

 def processed_values(list_of_io_tasks):
     pool = multiprocessing.Pool(4) # num workers
     results = pool.imap_unordered(slow_io_call, list_of_io_tasks)
     while True:
         yield results.next(9999999) # large time-out

请注意,您也可以在没有results循环的情况下直接迭代for item in results: yield item(例如while True),但是使用超时值调用results.next()可以解决此问题{ {3}}并允许您使用Ctrl-C终止主进程和所有子进程。另请注意,此函数中未捕获StopIteration异常,但当results.next()没有更多项返回时,将引发一个异常。这对于生成器函数是合法的,例如这个函数,当没有更多的值可以产生或者只是停止让步时,它们会引发StopIteration错误,代表它会引发StopIteration异常。

要使用线程代替进程,请替换
import multiprocessing

import multiprocessing.dummy as multiprocessing