python的多处理和concurrent.futures有什么区别?

Dav*_*ker 14 python multiprocessing concurrent.futures

在python中实现多处理的一种简单方法是

from multiprocessing import Pool

def calculate(number):
    return number

if __name__ == '__main__':
    pool = Pool()
    result = pool.map(calculate, range(4))
Run Code Online (Sandbox Code Playgroud)

基于期货的另一种实现方式是

from concurrent.futures import ProcessPoolExecutor

def calculate(number):
    return number

with ProcessPoolExecutor() as executor:
    result = executor.map(calculate, range(4))
Run Code Online (Sandbox Code Playgroud)

两种替代方案基本上都是相同的,但一个显着的区别是我们不必使用通常的if __name__ == '__main__'条款来保护代码.这是因为期货的实施照顾了这个还是我们有不同的原因?

更广泛地说,multiprocessing和之间有什么区别concurrent.futures?什么时候优先于另一个?

编辑:我最初假设防护if __name__ == '__main__'只是多处理所必需的是错误的.显然,对于Windows上的两种实现都需要这种保护,而在unix系统上则没有必要.

dan*_*ano 20

你实际上也应该使用if __name__ == "__main__"防护装置ProcessPoolExecutor:它multiprocessing.Process用于填充它Poolmultiprocessing.Pool底盖,就像它一样,因此所有关于可拾取性的警告(特别是在Windows上)等都适用.

根据Jesse Noller(一位Python核心撰稿人)所做的声明,当被问及为什么Python有这两种API时,我认为这ProcessPoolExecutor最终会被取代:multiprocessing.Pool

当我们熟悉API时,Brian和我需要处理我们打算进行的整合.我最终的目标是从MP中删除基本的multiprocessing.Process/Queue内容以及并发.*并支持线程后端.

就目前而言,与更简单(更有限)的API ProcessPoolExecutor完全相同multiprocessing.Pool.如果你可以ProcessPoolExecutor使用它,那就使用它,因为我认为它更有可能在长期内得到增强.

请注意,您可以使用所有的佣工来自multiprocessingProcessPoolExecutor一样Lock,Queue,Manager等,主要理由使用multiprocessing.Pool是如果你需要initializer/ initargs(虽然有一个开放的bug让那些加入到ProcessPoolExecutor),或maxtasksperchild.或者您正在运行Python 2.7或更早版本,并且不想安装(或要求您的用户安装)后端端口concurrent.futures.

编辑:

另外值得注意的是:根据这个问题,multiprocessing.Pool.map表现优于ProcessPoolExecutor.map.请注意,每个工作项的性能差异非常小,因此如果您在map非常大的可迭代项上使用,您可能只会注意到性能差异很大.性能差异的原因在于,multiprocessing.Pool将迭代的批处理传递到映射到块,然后将块传递给工作进程,这减少了父和子之间IPC的开销.ProcessPoolExecutor始终将一个项目从迭代中一次传递给子项,由于IPC开销增加,这会导致大型迭代的性能下降得更慢.好消息是这个问题将在Python 3.5中修复,因为chunksize已经添加了关键字参数ProcessPoolExecutor.map,如果你知道你正在处理大型迭代,可以用它来指定更大的块大小.有关详细信息,请参阅此错误.