【问题标题】:What is the difference between ProcessPoolExecutor and ThreadPoolExecutor?ProcessPoolExecutor 和 ThreadPoolExecutor 有什么区别?
【发布时间】:2018-08-13 18:50:14
【问题描述】:

我阅读了试图获得基本理解的文档,但它只表明ProcessPoolExecutor 允许回避Global Interpreter Lock,我认为这是锁定变量或函数的方法,这样并行进程就不会更新它同时具有价值。

我正在寻找的是何时使用ProcessPoolExecutor,何时使用ThreadPoolExecutor,以及在使用每种方法时我应该记住什么!

【问题讨论】:

    标签: python python-3.x multithreading parallel-processing python-3.5


    【解决方案1】:

    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 模块中的数据包装器。

    【讨论】:

    • 关于线程,为什么它对大量 HTTP 请求有好处?即我有 3 个请求和 3 个线程,每次 CPU 轮询其中一个线程并在获取数据方面取得了一点进展,这比从每个请求中一次一个地获取所有数据要好得多?我可以换个说法,当一个睡眠线程发送一个网络请求时,即使 CPU 运行另一个线程,他也会得到答案吗?如果是这样,怎么可能?
    【解决方案2】:

    ProcessPool 用于 CPU 密集型任务,因此您可以从多个 CPU 中受益。

    Threads 用于 io 绑定任务,因此您可以从 io wait 中受益。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-14
      • 2011-04-30
      • 2018-10-18
      • 1970-01-01
      • 2010-10-02
      • 2011-12-12
      • 2010-09-16
      • 2012-03-14
      相关资源
      最近更新 更多