ana*_*nya 3 python parallel-processing multithreading python-3.x python-3.5
我阅读了试图获得基本理解的文档,但它仅表明ProcessPoolExecutor
可以避开Global Interpreter Lock
我认为是锁定变量或函数的方式,从而使并行进程不会同时更新其值。
我要寻找的是何时使用ProcessPoolExecutor
,何时使用ThreadPoolExecutor
以及使用每种方法时应记住的事项!
小智 18
ProcessPool 用于 CPU 密集型任务,因此您可以从多个 CPU 中受益。
线程用于 io 绑定任务,因此您可以从 io 等待中受益。
ProcessPoolExecutor
在您自己的子进程中运行每个工人。
ThreadPoolExecutor
在主进程的不同线程中运行每个工作程序。
全局解释器锁定(GIL)不仅锁定变量或函数,还锁定其他变量或函数。它锁定整个解释器。这意味着每个内置操作(包括)listodicts[3]['spam'] = eggs
都自动是线程安全的。
但这也意味着,如果您的代码受CPU限制(也就是说,它花费时间进行计算,而不是例如等待网络响应),而不是将大部分时间都花在旨在释放GIL的外部库中(像NumPy),一次只能有一个线程拥有GIL。因此,如果您有4个线程,即使您有4个甚至16个内核,大多数情况下,其中3个将坐在那里等待GIL。因此,您的代码不会变得更快4倍,而是会变得更慢。
再次,对于受I / O约束的代码(例如,等待一堆服务器以响应您发出的一堆HTTP请求),线程就很好了。这仅是针对CPU绑定的代码的问题。
每个单独的子进程都有其自己的单独的GIL,因此,即使您的代码受CPU限制,这个问题也可以解决,使用4个子进程仍然可以使其运行速度几乎提高了4倍。
但是子进程不共享任何变量。通常,这是一件好事:将值的(副本)作为参数传递给函数,然后将值的(副本)返回,并且进程隔离保证您可以安全地进行此操作。但是有时(通常出于性能原因,有时还因为您传递了无法通过复制的对象pickle
),这是不可接受的,因此您需要使用线程,或者在其中使用更复杂的显式共享数据包装器该multiprocessing
模块。
归档时间: |
|
查看次数: |
2734 次 |
最近记录: |