【问题标题】:Python threads all executing on a single corePython 线程全部在一个内核上执行
【发布时间】:2011-05-28 15:44:36
【问题描述】:

我有一个 Python 程序,它产生许多线程,一次运行 4 个,每个都执行昂贵的操作。伪代码:

for object in list:
    t = Thread(target=process, args=(object))
    # if fewer than 4 threads are currently running, t.start(). Otherwise, add t to queue

但是当程序运行时,OS X 中的 Activity Monitor 显示 4 个逻辑内核中的 1 个处于 100%,其他的几乎为 0。显然我不能强迫操作系统做任何事情,但我已经以前从来没有关注过像这样的多线程代码的性能,所以我想知道我是否只是遗漏或误解了某些东西。

谢谢。

【问题讨论】:

    标签: python multithreading performance


    【解决方案1】:

    请注意,在许多情况下(以及几乎所有“昂贵操作”是在 Python 中实现的计算的情况),由于 Python 的 Global Interpreter Lock (GIL),多个线程实际上不会同时运行。

    GIL 是解释器级别的锁。 此锁可防止执行 在 Python 中一次多个线程 口译员。每个线程想要 运行必须等待 GIL 由另一个线程释放,它 意味着你的多线程 Python 应用程序本质上是单一的 穿线的,对吧?是的。不完全是。 有点像。

    CPython 使用所谓的“操作 系统”线程在封面下, 也就是说每次请求 制作一个新线程, 解释器实际上调用了 操作系统的库和 内核生成一个新线程。这 例如,与 Java 相同。所以 在记忆中你确实有多个 线程和通常的操作 系统控制哪个线程 预定运行。在多个 处理器机器,这意味着你 可能有许多线程分布在 多处理器,一切皆大欢喜 忙着工作。

    然而,虽然 CPython 确实使用 操作系统线程(理论上 允许多个线程执行 在口译员内 同时),口译员也 强制 GIL 被一个 线程才能访问 解释器和堆栈并且可以修改 内存中的 Python 对象全部 任性。后一点是为什么 GIL 存在:GIL 防止 同时访问 Python 对象 通过多个线程。但这并不 拯救你(如银行所示 示例)从对锁敏感 生物;你没有搭便车。 GIL 是为了保护 解释记忆,而不是你的理智。

    有关详细信息,请参阅Jesse Noller's post 的全局解释器锁定部分。

    要解决此问题,请查看Python's multiprocessing module

    多个进程(明智地使用 IPC) [...] 更好 为多 CPU 编写应用程序的方法 盒子而不是线程。

    -- Guido van Rossum (creator of Python)

    【讨论】:

    • 非常感谢您的详细回答-multiprocessing 是。对于其他感兴趣的人,multiprocessing.Pool 还解决了限制活动工作线程数量的问题。
    • 那我在 Windows 上该怎么办?多处理在 Windows 上很糟糕,因为子进程不会从父进程的内存中继承对象。我想将一个函数的多线程映射到一个大列表上。
    • 很好的答案。但是我仍然不清楚multiThreading。假设我的计算机有 4 个内核,我在 python 代码中创建了 4 个线程。据我了解,由于 GIL,这些线程将在 仅 1(物理)核心中生成,对吗?而在其他语言中,这些线程可以在不同的内核中产生?我不确定如何在物理内核中分配线程。线程是在同一个核心中严格创建的,还是依赖于其他东西(例如,操作系统、编程语言……)。谢谢。
    • @Catbuilts Python 并不规定在哪些物理内核上创建线程——这由操作系统控制。 GIL 所做的是限制线程在 Python 层所做的工作:一次只允许一个线程修改 Python 解释器的状态,因此任何其他尝试这样做的线程都将处于空闲状态,直到轮到它们操作。
    【解决方案2】:

    Python 有一个全局解释器锁,它可以防止解释代码的线程被并发处理。

    http://en.wikipedia.org/wiki/Global_Interpreter_Lock

    http://wiki.python.org/moin/GlobalInterpreterLock

    如需解决此问题的方法,请尝试multiprocessing module,如下所示:

    Does running separate python processes avoid the GIL?

    【讨论】:

    • 多进程不会受到 GIL 的影响,因为每个进程都有自己的 GIL 和自己的内存。
    • @Sven:感谢您的信息。我想知道在其他不使用 GIL 的编程语言中,线程可以在多进程上运行吗?例如,在 4 核计算机上创建一个有 4 个线程的程序,这些线程是否在所有四个核上执行? python 中的所有线程都只在 1 个核心上产生的原因是否在于 GIL
    【解决方案3】:

    AFAIK,在 CPython 中,全局解释器锁意味着在任何时候都不能运行超过一个 Python 代码块。尽管这并不会真正影响单处理器/单核机器中的任何内容,但在多核机器上,这意味着您在任何时候实际上只有一个线程在运行 - 导致所有其他内核处于空闲状态。

    【讨论】:

      猜你喜欢
      • 2023-04-02
      • 1970-01-01
      • 2014-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-05
      相关资源
      最近更新 更多