Python 3.2引入了Concurrent Futures,它似乎是旧的线程和multiprocessing模块的一些高级组合。
与较旧的多处理模块相比,将此功能用于与CPU绑定(bind)的任务有什么优点和缺点?
This article建议他们使用起来容易得多-是这样吗?
最佳答案
我不会将concurrent.futures
称为“高级”,它是一个更简单的接口(interface),其工作原理几乎相同,无论您使用多个线程还是多个进程作为基础并行化头。
因此,几乎像所有“简单界面”实例一样,都涉及相同的折衷:学习曲线较浅,很大一部分是因为可供学习的资源少得多。但是,由于它提供的选项较少,因此最终可能使您无法使用更丰富的界面而感到沮丧。
就与CPU绑定(bind)的任务而言,这还不够具体,以至于说不出什么意义。对于CPython下与CPU绑定(bind)的任务,您需要多个进程而不是多个线程才能获得加速的机会。但是,获得多少加速(如果有)取决于硬件,操作系统的详细信息,尤其取决于特定任务需要多少进程间通信。在幕后,所有进程间并行化头都依赖于相同的OS原语-用于获得这些原语的高级API并不是底线速度的主要因素。
编辑:示例
这是您引用的文章中显示的最终代码,但是我添加了一个导入语句以使其正常工作:
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方面缺乏免费的新颖性。关于python - Python 3中的Concurrent.futures与Multiprocessing,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20776189/