在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__'
子句来保护代码。这是因为期货的实施照顾了这一点还是我们有不同的原因?更广泛地说,
multiprocessing
和concurrent.futures
之间有什么区别?什么时候一个比另一个更受欢迎?编辑:
我最初的假设是guard
if __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
,那么就使用它,因为我认为从长远来看,它更有可能得到增强。
请注意,您可以使用来自multiprocessing
和ProcessPoolExecutor
的所有助手,如Lock
、Queue
、Manager
等。使用multiprocessing.Pool
的主要原因是,如果您需要initializer
/initargs
(尽管有一个this statement made by Jesse Noller来获取添加到processPoolexecutor的助手),或maxtasksperchild
。或者您运行的是python 2.7或更早版本,不想安装(或要求用户安装)concurrent.futures
的后端。
编辑:
同样值得注意的是:根据open bug,multiprocessing.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/