Python 3.2引入了Concurrent Futures,它似乎是旧版线程和multiprocessing模块的一些高级组合。
与旧的多处理模块相比,在CPU绑定任务中使用它有什么优缺点?
This article表示他们更容易合作 - 是这样吗?
我不会将concurrent.futures
称为“高级” - 它是一个更简单的接口,无论您使用多个线程还是多个进程作为底层并行化噱头,它的工作方式都非常相似。
因此,与几乎所有“简单界面”的实例一样,涉及的权衡也大致相同:它的学习曲线较浅,很大程度上只是因为可用的学习量较少;但是,因为它提供的选项较少,它最终可能会让您以更丰富的界面不会让您感到沮丧。
到目前为止,受CPU约束的任务仍然存在,而且这个任务太低,而且说得太有意义了。对于CPython下的CPU绑定任务,您需要多个进程而不是多个线程才有机会获得加速。但是,获得多少(如果有的话)加速取决于硬件,操作系统的细节,特别是您的特定任务需要多少进程间通信。在幕后,所有进程间并行化噱头都依赖于相同的操作系统原语 - 用于获取这些原语的高级API不是底线速度的主要因素。
编辑:示例
这是您引用的文章中显示的最终代码,但我添加了一个使其工作所需的import语句:
from concurrent.futures import ProcessPoolExecutor
def pool_factorizer_map(nums, nprocs):
# Let the executor divide the work among processes by using 'map'.
with ProcessPoolExecutor(max_workers=nprocs) as executor:
return {num:factors for num, factors in
zip(nums,
executor.map(factorize_naive, nums))}
这与使用multiprocessing
完全相同:
import multiprocessing as mp
def mp_factorizer_map(nums, nprocs):
with mp.Pool(nprocs) as pool:
return {num:factors for num, factors in
zip(nums,
pool.map(factorize_naive, nums))}
请注意,在Python 3.3中添加了使用multiprocessing.Pool
对象作为上下文管理器的功能。
哪一个更容易使用?哈哈;-)他们基本相同。
一个不同之处在于,Pool
支持这么多不同的做事方式,你可能不会意识到在你爬上学习曲线之前是多么容易。
同样,所有这些不同的方式都是力量和弱点。它们是一种优势,因为在某些情况下可能需要灵活性。它们是一个弱点,因为“最好只有一种明显的方法”。一个专门(如果可能的话)坚持concurrent.futures
的项目从长远来看可能更容易维护,因为缺乏关于如何使用其简约API的无偿新颖性。