Python线程都在一个核心上执行

Rob*_*ens 56 python performance multithreading

我有一个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
Run Code Online (Sandbox Code Playgroud)

但是当程序运行时,OS X中的Activity Monitor显示4个逻辑核心中的1个处于100%而其他核心处于接近0的状态.显然,我不能强制操作系统做任何事情,但我从来没有做过注意这样的多线程代码中的性能,所以我想知道我是否只是缺少或误解了一些东西.

谢谢.

Gab*_*ant 72

请注意,在许多情况下(实际上所有情况下,"昂贵的操作"都是在Python中实现的计算),由于Python的全局解释器锁(GIL),多个线程实际上不会同时运行.

GIL是一个解释器级锁.此锁定可防止在Python解释器中同时执行多个线程.每个想要运行的线程必须等待另一个线程释放GIL,这意味着你的多线程Python应用程序本质上是单线程的,对吧?是.不完全是.有点.

CPython使用所谓的"操作系统"线程,也就是说每次创建新线程的请求时,解释器实际调用操作系统的库和内核来生成新线程.例如,这与Java相同.所以在内存中你确实有多个线程,通常操作系统控制调度运行的线程.在多处理器计算机上,这意味着您可以将多个线程分布在多个处理器上,所有这些都可以快乐地完成工作.

但是,虽然CPython确实使用操作系统线程(理论上允许多个线程同时在解释器中执行),但解释器还强制GIL在它可以访问解释器和堆栈之前被线程获取并且可以修改内存中的Python对象所有人都不知道.后一点是GIL存在的原因:GIL阻止多个线程同时访问Python对象.但这并不能使你(如银行的例子所示)成为一个锁定敏感的生物; 你没有搭便车.GIL是为了保护口译员的记忆,而不是你的理智.

有关详细信息,请参阅Jesse Noller帖子的Global Interpreter Lock部分.

要解决此问题,请查看Python的多处理模块.

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

- Guido van Rossum(Python的创建者)

  • 非常感谢您的详细解答 - "多处理"就是这样.对于其他感兴趣的人来说,`multiprocessing.Pool`也处理了限制活动工作线程数量的问题. (3认同)
  • 好答案。但是我仍然不清楚* multiThreading *。假设我的计算机有4个内核,并且在python代码中创建了4个线程。据我了解,由于GIL,这些线程将仅在1个(物理)内核中生成,对吗?而在其他语言中,这些线程可以生成在不同的内核中吗?我不确定如何在物理核心中分配线程。线程是严格在同一内核中创建还是依赖于其他内核(例如,操作系统,编程语言等)。谢谢。 (3认同)
  • @Catbuilts Python 并没有规定在哪个物理核心上创建线程——这是由操作系统控制的。GIL 所做的是限制线程在 Python 层所做的工作:一次只允许一个线程修改 Python 解释器的状态,因此任何其他尝试这样做的线程都将闲置,直到轮到它们操作。 (2认同)

T.R*_*.R. 9

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

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

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

有关解决此问题的方法,请尝试使用多处理模块,如下所示:

运行单独的python进程是否避免了GIL?


MAK*_*MAK 6

AFAIK,在 CPython 中,全局解释器锁意味着同一时间不能运行多个 Python 代码块。虽然这对单处理器/单核机器没有任何影响,但在多核机器上,这意味着任何时候实际上只有一个线程在运行 - 导致所有其他核心处于空闲状态。