在Python中实现多处理的一个简单方法是

from multiprocessing import Pool

def calculate(number):
    return number

if __name__ == '__main__':
    pool = Pool()
    result = pool.map(calculate, range(4))

基于未来的另一种实现是
from concurrent.futures import ProcessPoolExecutor

def calculate(number):
    return number

with ProcessPoolExecutor() as executor:
    result = executor.map(calculate, range(4))

这两种选择在本质上都是相同的,但一个显著的区别是,我们不必使用通常的if __name__ == '__main__'子句来保护代码。这是因为期货的实施照顾了这一点还是我们有不同的原因?
更广泛地说,multiprocessingconcurrent.futures之间有什么区别?什么时候一个比另一个更受欢迎?
编辑:
我最初的假设是guardif __name__ == '__main__'只对多处理是必要的,这是错误的。显然,在Windows上的两种实现都需要这种保护,而在UNIX系统上则不需要这种保护。

最佳答案

实际上,您也应该将if __name__ == "__main__"保护与ProcessPoolExecutor一起使用:它使用multiprocessing.Process来填充其覆盖物下的Pool,就像multiprocessing.Pool一样,因此所有关于可选择性的警告(尤其是在Windows上)都适用。
我相信,当被问及为什么python有两个API时,根据(一个python核心贡献者),ProcessPoolExecutor意味着最终要替换multiprocessing.Pool
布赖恩和我需要努力实现我们计划(ed)的合并
当人们对这些API感到满意时。我的最终目标是
除了基本的multiprocessing.process/queue之外的任何东西
并将其转换为concurrent.*并为其支持线程后端。
现在,ProcessPoolExecutor正在使用更简单(更有限)的API执行与multiprocessing.Pool完全相同的操作。如果你可以不使用ProcessPoolExecutor,那么就使用它,因为我认为从长远来看,它更有可能得到增强。
请注意,您可以使用来自multiprocessingProcessPoolExecutor的所有助手,如LockQueueManager等。使用multiprocessing.Pool的主要原因是,如果您需要initializer/initargs(尽管有一个this statement made by Jesse Noller来获取添加到processPoolexecutor的助手),或maxtasksperchild。或者您运行的是python 2.7或更早版本,不想安装(或要求用户安装)concurrent.futures的后端。
编辑:
同样值得注意的是:根据open bugmultiprocessing.Pool.map表现优于ProcessPoolExecutor.map。请注意,每个工作项的性能差异非常小,因此,如果在一个非常大的iterable上使用map性能差异的原因是,multiprocessing.Pool将批处理传递给映射成块的iterable,然后将块传递给工作进程,从而减少父进程和子进程之间的IPC开销。ProcessPoolExecutor总是将一个项从iterable一次传递给子项,这会导致较大iterables的性能变慢,因为增加了IPC开销。好消息是,这个问题将在python 3.5中得到解决,因为关键字参数已经添加到chunksize中,如果您知道要处理大型iterables,可以使用它来指定更大的块大小。有关更多信息,请参阅此this question

关于python - python的多处理和concurrent.futures有什么区别?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24896193/

10-13 07:24