python GIL 问题(multiprocessing和ctypes)
来源:互联网 发布:中控矩阵系统 编辑:程序博客网 时间:2024/04/19 21:19
GIL全称Global Interpreter Lock 全局解释器锁(货真价实的全局线程锁)
我们先来看一个问题。运行下面这段 python 代码,CPU 占用率是多少?
# 请勿在工作中模仿,危险:)def dead_loop(): while True: passdead_loop()
答案是什么呢,占用 100% CPU?那是单核!还得是没有超线程的古董 CPU。在我的双核 CPU 上,这个死循环只会吃掉我一个核的工作负荷,也就是只占用 50% CPU。那如何能让它在双核机器上占用 100% 的 CPU 呢?答案很容易想到,用两个线程就行了,线程不正是并发分享 CPU 运算资源的吗。可惜答案虽然对了,但做起来可没那么简单。下面的程序在主线程之外又起了一个死循环的线程
import threadingdef dead_loop(): while True: pass# 新起一个死循环线程t = threading.Thread(target=dead_loop)t.start()# 主线程也进入死循环dead_loop()t.join()
按道理它应该能做到占用两个核的 CPU 资源,可是实际运行情况却是没有什么改变,还是只占了 50% CPU 不到。打开 system monitor 一探究竟,这个占了 50% 的 python 进程确实是有两个线程在跑。那这两个死循环的线程为何不能占满双核 CPU 资源呢?其实幕后的黑手就是 GIL。
在 Python 语言的主流实现 CPython 中,GIL 是一个货真价实的全局线程锁,在解释器解释执行任何 Python 代码时,都需要先获得这把锁才行,在遇到 I/O 操作时会释放这把锁。如果是纯计算的程序,没有 I/O 操作,解释器会每隔 100 次操作就释放这把锁,让别的线程有机会执行(这个次数可以通过 sys.setcheckinterval 来调整)。所以虽然 CPython 的线程库直接封装操作系统的原生线程,但 CPython 进程做为一个整体,同一时间只会有一个获得了 GIL 的线程在跑,其它的线程都处于等待状态等着 GIL 的释放。这也就解释了我们上面的实验结果:虽然有两个死循环的线程,而且有两个物理 CPU 内核,但因为 GIL 的限制,两个线程只是做着分时切换,总的 CPU 占用率还略低于 50%。
让我们回到本文最初的那个问题:如何能让这个死循环的 Python 脚本在双核机器上占用 100% 的 CPU?其实最简单的答案应该是:运行两个 python 死循环的程序!也就是说,用两个分别占满一个 CPU 内核的 python 进程来做到。确实,多进程也是利用多个 CPU 的好方法。只是进程间内存地址空间独立,互相协同通信要比多线程麻烦很多。有感于此,Python 在 2.6 里新引入了 multiprocessing 这个多进程标准库,让多进程的 python 程序编写简化到类似多线程的程度,大大减轻了 GIL 带来的不能利用多核的尴尬。
ctypes 与 Python 扩展不同,它可以让 Python 直接调用任意的 C 动态库的导出函数。你所要做的只是用 ctypes 写些 python 代码即可。最酷的是,ctypes 会在调用 C 函数前释放 GIL。所以,我们可以通过 ctypes 和 C 动态库来让 python 充分利用物理内核的计算能力
- python GIL 问题(multiprocessing和ctypes)
- python 线程,GIL 和 ctypes
- python 线程,GIL 和 ctypes
- python 线程,GIL 和 ctypes
- python 线程,GIL 和 ctypes
- python 线程,GIL 和 ctypes
- python 线程,GIL 和 ctypes
- python 线程,GIL 和 ctypes
- python 线程,GIL 和 ctypes
- python 线程,GIL 和 ctypes
- python 线程,GIL 和 ctypes(转)
- Python, GIL, ctypes, Jython 多线程
- 使用multiprocessing包规避Python GIL多线程串行问题
- Python中的GIL问题
- python线程和GIL
- python线程_GIL和ctypes
- multiprocessing(python 版)
- python之Thread和multiprocessing
- 安卓6.0动态权限配置查询
- CF 55D beautiful number(数位dp)
- Docker实践-使用maven插件自动部署web应用至Docker容器的tomcat
- centos locate 命令安装
- Altium Designer Summer 16中如何实现元件自动编号
- python GIL 问题(multiprocessing和ctypes)
- Kotlin(八)
- setAudioSource failed 异常问题
- Nginx随写
- 同步加载、异步加载、延迟加载
- 转存Druid监控记录到日志文件
- curl post base64 jpeg图片精简版
- servlet的初始化过程
- Ubuntu下Android源码的获取(Android4.4为例)