Python 3.2引入了Concurrent Futures,这似乎是较旧的线程和多处理模块的一些高级组合。
与较旧的多处理模块相比,将此功能用于与CPU绑定的任务有什么优点和缺点?
本文建议他们更容易使用-是这样吗?
Python 3.2引入了Concurrent Futures,这似乎是较旧的线程和多处理模块的一些高级组合。
与较旧的多处理模块相比,将此功能用于与CPU绑定的任务有什么优点和缺点?
本文建议他们更容易使用-是这样吗?
Answers:
我不会称其为concurrent.futures
“高级”,它是一个更简单的接口,其工作原理几乎相同,无论您使用多个线程还是多个进程作为基础并行化ization头。
所以,像“简单的界面”的几乎所有情况下,大同小异的取舍都参与:它有一个浅的学习曲线,这在很大程度上只是因为有可用的要少得多,以学习; 但是,由于它提供的选项较少,最终可能会以丰富的界面无法实现的方式使您感到沮丧。
就与CPU绑定的任务而言,这还不够具体,以至于说不出什么意义。对于CPython下与CPU绑定的任务,您需要多个进程而不是多个线程才能获得加速的机会。但是,获得多少加速(如果有)取决于硬件,操作系统的详细信息,尤其取决于特定任务需要多少进程间通信。在幕后,所有进程间并行化头都依赖于相同的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))}
请注意,multiprocessing.Pool
在Python 3.3中添加了使用对象作为上下文管理器的功能。
哪一个更容易使用?大声笑;-)他们本质上是相同的。
一个区别是Pool
支持这样的事情,你可能不知道是多么容易的许多不同的方式可以是直到你攀上了学习曲线相当一路上扬。
同样,所有这些不同的方式都是优点和缺点。它们是优势,因为在某些情况下可能需要灵活性。它们之所以成为弱点,是因为“最好只有一种明显的方法”。concurrent.futures
从长远来看,专案(如果可能)坚持下去的项目可能会更容易维护,因为在如何使用其最小限度的API方面缺乏免费的新颖性。
ProcessPoolExecutor
实际上具有更多的选择,Pool
因为ProcessPoolExecutor.submit
返回Future
允许取消的实例(cancel
),检查引发了哪个异常(exception
),并在完成时动态添加要调用的回调(add_done_callback
)。AsyncResult
由返回的实例无法使用这些功能Pool.apply_async
。在其他方面Pool
做出了应有的更多选项initializer
/ initargs
,maxtasksperchild
和context
在Pool.__init__
,多方法,通过暴露的Pool
实例。
Pool
,而是关于模块的。 Pool
只是其中的一小部分multiprocessing
,而且在文档中如此之低,人们需要一段时间才能意识到它甚至存在于中multiprocessing
。这个特定的答案侧重于此,Pool
因为这是OP链接到的所有文章,并且cf
“使用起来容易得多”,对于该文章所讨论的内容根本不正确。除此之外,cf
的as_completed()
也可以很方便的。