我有一个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的状态。显然我不能强迫操作系统做任何事情,但我已经从来没有像以前那样关注多线程代码中的性能,所以我想知道我是否只是缺少或误解了一些东西。
感谢。
答案 0 :(得分:64)
请注意,在许多情况下(几乎所有“昂贵的操作”都是在Python中实现的计算的情况),由于Python的Global Interpreter Lock (GIL),多个线程实际上不会同时运行。
GIL是一个解释器级锁。 此锁定可防止执行 Python中同时存在多个线程 翻译。每个想要的线程 运行必须等待GIL 由其他线程发布,其中 意味着你的多线程Python 申请基本上是单一的 有线的,对吧?是。不完全是。 排序。
CPython使用所谓的“操作” 系统“线下的线程, 也就是说每次请求 做一个新线程, 口译员实际上是打电话给 操作系统的库和 内核生成一个新线程。这个 例如,与Java相同。所以 在记忆中你确实有多个 线程,通常是操作 系统控制哪个线程 计划运行。在多个 处理器机器,这意味着你 可能有很多线程分散 多个处理器,都很开心 匆匆忙忙做工作。
然而,虽然CPython确实使用了 操作系统线程(理论上讲 允许多个线程执行 在翻译中 同时),翻译也 迫使GIL被a获得 线程才可以访问 解释器和堆栈,可以修改 所有内存中的Python对象 不管三七二十一。后一点是原因 GIL存在:GIL阻止 同时访问Python对象 通过多个线程。但事实并非如此 救你(如银行所示 来自锁定敏感 生物;你没有搭便车。 GIL是为了保护 口译记忆,而不是你的理智。
有关详情,请参阅Jesse Noller's post的Global Interpreter Lock部分。
要解决此问题,请查看Python's multiprocessing module。
多个流程(明智地使用 IPC)好多了 为多CPU编写应用程序的方法 盒子而不是线程。
答案 1 :(得分:9)
Python有一个全局解释器锁,它可以防止解释代码的线程被并发处理。
http://en.wikipedia.org/wiki/Global_Interpreter_Lock
http://wiki.python.org/moin/GlobalInterpreterLock
有关解决此问题的方法,请按照此处的建议尝试multiprocessing module:
答案 2 :(得分:2)
AFAIK,在CPython中,Global Interpreter Lock意味着任何时候都不能运行多个Python代码块。虽然这并不会真正影响单个处理器/单核机器中的任何内容,但在多路计算机上,这意味着您实际上每次只运行一个线程 - 导致所有其他内核空闲。