- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Python 有可能删除 GIL 吗?由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
我们知道,在 CPython 中,有一个全局解释器锁,英文叫 global interpreter lock,简称 GIL,是一个互斥锁,用来保护 Python 世界里的对象,防止同一时刻多个线程执行 Python 的字节码,从而确保线程安全,这导致了 Python 的线程无法利用多核 CPU 的优势,因此有人说 Python 的多线程是伪多线程,性能不高,那么 Python 将来有可能去除 GIL 吗?
要回答这个问题,先从 GIL 的起源进行分析.
Python 第一次发布是在 1991 年,当时的 CPU 都是单核,单核中,多线程主要为了一边做IO,一边做 CPU 计算而设计的,Python 编译器是由 C 语言编写的,因此也叫 CPython,那时候很多编程语言没有自动内存管理的功能,为了实现自动垃圾回收,Python 为每一个对象进行了引用计数,当引用计数为 0 的时候说明该对象可以回收,从而释放内存了,比如:
1
2
3
4
5
6
|
>>>
import
sys
>>> data
=
{
'gzh'
:
'Python七号'
}
>>> var1
=
data
>>> sys.getrefcount(data)
3
>>>
|
这里 data 对象就有 3 个引用, 一个是本身,一个是变量 var1,一个是 getrefcount 函数的参数,如果此时又有一个线程引用了 data,那么引用计数再增加 1,如果某个线程使用了 data 后运行结束,那么引用计数就减少 1,多线程对同一个变量「引用计数」进行修改,就会遇到 race conditions(竞争),为了避免 race conditions,最简单有效的办法就是加一个互斥锁.
如果对每一个对象都加锁,有可能引发另一个问题,就是死锁,而且频繁的获取和释放会导致性能下降,最简单有效的方法就是加一个解释器锁,线程在执行任何字节码时都先获取解释器锁,这就避免了死锁,而且不会有太多的性能消耗。当时 CPU 都是单核,而且这种 GIL 设计简单,并不会影响性能,因此一直沿用至今天。GIL 存在最主要的原因,就是因为 Python 的内存管理不是线程安全的,这就是 GIL 产生并存在的主要缘由.
CPU 进入多核时代后,可以同时做多个计算任务, GIL 才真正变成问题。在 1999 年,有个叫 Greg Stein 的大佬基于 Python 1.5 版本消除了 GIL,取代代之的是在可变数据结构上加上更细粒度的锁,也提交了补丁用于去除对全局可变对象的依赖,然后在标准测试时表明去除 GIL 后单线程比不去除时慢了近 2 倍,测试的机器还是当时性能最好 Windows 机器。也就是说除去了 GIL 后,你使用 2 个 CPU 才能获取比原来 1 个 CPU 稍微好一点的性能,这种提升明显得不偿失,Greg Stein 的尝试也就失败告终.
Python 之父 Guido van Rossum 也欢迎社区的志愿者去尝试去除 GIL,只要不降低单线程的性能,但他也提到,去掉 GIL 不是一件容易的事.
Python 开发者邮件列表中也偶尔会有去除 GIL 的议题,但是以下需求必须满足:
有些需求不容易被满足,比如 4,5,7,目前,还没有人满足以上需求的同时去除 GIL 成功的.
这些年 Python 实在太火了,很多优秀的库都是基于 CPython 进行编写的,很多都是 90 年代的 C 扩展库,如果要除去 GIL,那么很多基于 GIL 编写的 C 扩展便无法使用,也就是去了 GIL,Python 生态有很多扩展或三方库者无法使用.
还有一个很明显的例子,Python 解释器不止有 CPython,还有用 Java 编写的 Python,.NET 实现的 IronPython,这些解释器完全没有 GIL,可是有多少人为它们编写扩展呢?
Python 之所以如此火爆,与它有着丰富的三方库开箱即用有着很大的关系,积重难返,去除 GIL 很困难.
Python3 在最开始时是有机会实现很多新功能,在此过程中,打破了一些现有的 C 扩展,然后需要更新和移植更改以配合 Python 3,这也是 Python3 一开始不被社区所接受的原因.
与 Python2 相比,删除 GIL 将使 Python3 在单线程性能方面更慢,而且很多优秀的扩展将不能再使用,如果真的这样,可以想象 Python3 不可能有未来,最终的结果是 Python3 仍然保持有 GIL.
但 Python3 也为现有的 GIL 带来了重大改进,在 Python 3.2 版本中,确保了计算密集型线程和 I/O 密集型线程并存时, I/O 密集型长期获取不到 GIL 而无法执行的问题,提升了多线程的性能.
Python 因为内存管理不是线程安全的,因此自出生起就自带 GIL,然后很多扩展都是在 GIL 的保护下编写的,时间一长积重难反,Python3 一开始也因去除 GIL 导致单线程性能下降的问题而保留 GIL,现在已经是 Python3.9 版本了,将来 Python 去除 GIL 的可能性微乎其微,换句话说,去除 GIL 的 Python 也就不是我们认识的 Python 了.
不过不必沮丧,GIL 影响的也仅仅是多线程执行计算密集型的任务罢了,这种场景大多数程序员都很少遇到,即使有,可以使用多进程来避免 GIL 的影响,或者使用其他编程语言实现,任何编程语言或技术都不是十全十美的,发挥所长是最重要的,即使有 GIL,我也不在乎,也会依然使用 Python.
以上就是Python 有可能删除 GIL 吗?的详细内容,更多关于Python 删除 GIL 的资料请关注我其它相关文章! 。
原文链接:https://cloud.tencent.com/developer/article/1799500 。
最后此篇关于Python 有可能删除 GIL 吗?的文章就讲到这里了,如果你想了解更多关于Python 有可能删除 GIL 吗?的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我已经配置了我的环境,以便我可以将适当制作的 .png 文件加载到如下定义的图像中: boost::gil::rgb8_image_t input; 但是我如何加载任何典型类型的 pn
我已经配置了我的环境,以便我可以将适当制作的 .png 文件加载到如下定义的图像中: boost::gil::rgb8_image_t input; 但是我如何加载任何典型类型的 pn
它本质上是这个问题的延伸 - Usage of threadpoolexecutor in conjunction with cython's nogil 在这种情况下,我的 getArea2() 方
我意识到写信给 gil::color_converted_view不影响底层 View 的数据。我想知道这是否正确? 例如,假设我想编写一个程序,获取红色 channel 的值并将蓝色 channel
我有一个 Python 程序,因为它太大了,这里是它的源代码的链接: Link 当我在 Mac 上运行它时,有时会遇到这个奇怪的异常: Fatal Python error: PyEval_Resto
Wikipedia文章Global interpreter lock指示Raku具有全局解释器锁。 这与Curtis Poe's response到Are any companies planning
如果一个线程正在等待阻塞 I/O,Ruby 互斥体是否允许两个线程同时执行? 这是我对 GIL 如何用于 MRI 的理解。我很好奇互斥锁和 GIL 之间有什么区别吗? 最佳答案 是的,这有效。正因为如
我不太确定GIL是如何实现的,但理论上,如果我使用pyinstaller将python脚本编译成exe ,还会实现GIL吗?有什么办法可以绕过这个吗? 最佳答案 如果您使用 CPython(“标准 P
我将 Python 3.2 嵌入到 C++ 应用程序中,并且我有几个在程序中不同时间运行的子解释器(由 Py_NewInterpreter 创建)。他们在不同时间获取和释放 GIL,但当我想销毁其中一
阅读各种解释 GIS 和 Python 线程的文章后,Are locks unnecessary in multi-threaded Python code because of the GIL?这是
有没有办法剖析 python 进程对 GIL 的使用情况?基本上,我想知道持有 GIL 的时间百分比。该进程是单线程的。 我的动机是我有一些用 Cython 编写的代码,它使用 nogil。理想情况下
我正在重新表述我的问题,因为我认为很多人认为这是“Python 有线程吗”的问题。确实如此,但 CPython 也有 GIL,它在任何给定时间都不会调度多个线程。这使得 CPython 线程对于 CP
我想将我的单线程应用程序与工作线程数分开。只有 1 个问题 - 这个 Action 的表现如何?如果 GIL 阻止 python 同时执行超过 1 个线程,我会有任何 yield 吗? 另一点(从 c
在 python 中,我定义了一个全局变量,它被不同的线程读取/递增。由于 GIL,如果不使用任何类型的锁定机制,这是否会导致问题? 最佳答案 GIL 只要求解释器在另一个线程接管之前完全执行单个字节
假设我有一个线程和程序的主要部分。由于 GIL,一个线程应该一次工作(而不是同时工作)吗?但是,如果其中一个线程是一个无限循环(或两者都是无限循环)怎么办? 这两个进程会并行运行吗? def test
我正在阅读有关 GIL 的内容,但它从未真正指定它是否包含主线程(我假设是这样)。我问的原因是因为我有一个带有修改字典的线程设置的程序。主线程根据玩家输入添加/删除,而线程循环数据更新和更改数据。 然
我试图找到一个函数来告诉我当前线程是否具有全局解释器锁。 Python/C-API 文档似乎没有包含这样的函数。 我目前的解决方案是使用 PyGILState_Ensure() 获取锁,然后使用 Py
CPython 使用 Global Interpreter Lock . Linux 已删除 Big Kernel Lock 的所有痕迹.这些锁的替代品是什么?一个系统如何才能充分利用一个真正的多核或
CPU-bound(计算密集型) 和I/O bound(I/O密集型) 计算密集型任务(CPU-bound) 的特点是要进行大量的计算,占据着主要的任务,消耗CPU资源,一直处于满负荷状态。比如复
我的部分工作需要大量计算,但它们通常相当简单,原则上可以很容易地与 Cython 的 prange 并行完成,需要 nogil。但是,鉴于我尝试编写 Cython 代码,重点是将 cdef 类作为构建
我是一名优秀的程序员,十分优秀!