【问题标题】:Python 2.7 concurrent.futures.ThreadPoolExecutor does not parallelizePython 2.7 concurrent.futures.ThreadPoolExecutor 不并行化
【发布时间】:2015-08-03 10:19:20
【问题描述】:

我在基于 Intel i3 的机器上运行以下代码,该机器具有 4 个虚拟内核(2 个超线程/物理内核,64 位)并安装了 Ubuntu 14.04:

n = multiprocessing.cpu_count()
executor = ThreadPoolExecutor(n)
tuple_mapper = lambda i: (i, func(i))
results = dict(executor.map(tuple_mapper, range(10)))

代码似乎不是以并行方式执行的,因为 CPU 的持续使用率只有 25%。在利用率图表上,一次只有 4 个虚拟内核中的一个被 100% 使用。使用的核心每 10 秒左右交替一次。

但并行化在具有相同软件设置的服务器机器上运行良好。我不知道确切的内核数量或确切的处理器类型,但我确定它有几个内核并且利用率为 100%,并且计算速度加快(使用并行化后速度提高了 10 倍,使一些实验)。

我希望并行化也可以在我的机器上工作,而不仅仅是在服务器上。

为什么它不起作用?它与我的操作系统设置有关吗?我必须更改它们吗?

提前致谢!

更新: 有关背景信息,请参阅下面的正确答案。为了完整起见,我想给出一个解决问题的示例代码:

tuple_mapper = lambda i: (i, func(i))
n = multiprocessing.cpu_count()
with concurrent.futures.ProcessPoolExecutor(n) as executor:
    results = dict(executor.map(tuple_mapper, range(10)))

在重用它之前,请注意您正在使用的所有函数都在模块的顶层定义,如下所述: Python multiprocessing pickling error

【问题讨论】:

  • 试试ProcessPoolExecutor。可能是GIL
  • 很有趣,但是我仍然对服务器显示 100% 利用率和没有并行化的事实感到恼火,因为它具有相同的软件软件设置。我会试试你的建议。

标签: python linux ubuntu parallel-processing


【解决方案1】:

听起来您正在看到 Python 的 Global Interpreter Lock(又名 GIL)的结果。

在 CPython 中,全局解释器锁或 GIL 是一个互斥锁, 防止多个本机线程在以下位置执行 Python 字节码 一次。

由于您的所有线程都在运行纯 Python 代码,因此实际上只有一个线程可以并行运行。这应该会导致只有一个 CPU 处于活动状态并且符合您对问题的描述。

您可以通过使用来自同一模块的ProcessPoolExecutor 的多个进程来解决它。其他解决方案包括切换到没有 GIL 的 Jython 或 IronPython。

ProcessPoolExecutor 类是使用池的 Executor 子类 异步执行调用的进程。 ProcessPoolExecutor 使用 多处理模块,允许它绕过全局 解释器锁定,但也意味着只有可腌制的对象可以 执行并返回。

【讨论】:

  • 谢谢,现在我的 CPU 使用率达到 100%!在解决这个问题的过程中,我还必须在它起作用之前解决以下错误:stackoverflow.com/questions/8804830/…
  • 为什么不用pypy?我相信 pypy 也没有 GIL。
  • @0xc0de 根据其FAQ,PyPy 仍有 GIL
  • 我的 Jupyter Notebook 中的 Python 3.5 存在这个问题 也必须切换到 ProcessPoolExecutor 才能看到 100% 的 CPU 使用率 - 是出于同样的原因吗?
猜你喜欢
  • 2022-11-02
  • 1970-01-01
  • 2018-08-25
  • 2019-11-14
  • 2019-07-13
  • 1970-01-01
  • 2014-02-04
  • 2017-12-12
  • 2014-10-17
相关资源
最近更新 更多