热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

PythonGIL被杀了吗?

2003年初,英特尔推出了新的Pentium4“HT”处理器。该处理器的主频为3GHz,并具有“超线程”技术。在接下来的几年中,英特尔和A

2003年初,英特尔推出了新的Pentium 4“ HT”处理器。 该处理器的主频为3 GHz,并具有“超线程”技术。

在接下来的几年中,英特尔和AMD一直在通过提高总线速度,L2缓存大小和减小裸片大小以最大程度地减少延迟来争取最佳台式计算机性能。 3Ghz HT于2004年被时钟频率高达4 GHz的“ Prescott”型号580取代。

更高的时钟频率似乎是提高性能的前进方向,但是CPU受到高功耗和温暖地球的热量输出的困扰。

台式机中是否有4Ghz CPU? 不太可能,因为提高性能的方法是更高的总线速度和多核。 英特尔酷睿2在2006年取代了奔腾4,时钟速度大大降低。

除了发布消费型多核CPU之外,2006年还发生了其他事情,Python 2.5也发布了! Python 2.5附带了您熟悉和喜欢的with语句的beta版本。

当使用Intel的Core 2或AMD的Athlon X2时,Python 2.5有一个主要限制。

GIL。

什么是GIL?

GIL或全局解释器锁是Python解释器中的一个布尔值,受互斥锁保护。 CPython中的核心字节码评估循环使用该锁来设置当前正在执行语句的线程。

CPython在单个解释器中支持多个线程,但是线程必须请求访问GIL才能执行操作码(低级操作)。 反过来,这意味着Python开发人员可以利用异步代码,多线程代码,而不必担心获取任何变量的锁或使进程因死锁而崩溃。

GIL使使用Python进行多线程编程变得简单。

GIL还意味着,尽管CPython可以是多线程的,但在任何给定时间只能执行1个线程。 这意味着您的四核CPU正在执行此操作-(希望减去蓝屏)

当前版本的GIL 写于2009年 ,以支持异步功能,即使在多次尝试删除或降低对GIL的要求后,它仍未受影响。

任何删除GIL的建议的要求是,它不应降低任何单线程代码的性能。 早在2003年启用超线程的任何人都会欣赏为什么这很重要 。

在CPython中避免GIL

如果要在CPython中使用真正的并发代码,则必须使用多个进程。

在CPython 2.6中, 多处理模块已添加到标准库中。 多重处理是CPython进程(每个都有自己的GIL)的产生的包装器-

from multiprocessing import Process def f(name): print 'hello', name if __name__ == '__main__': p = Process(target=f, args=('bob',)) p.start() p.join()

可以生成进程,通过已编译的Python模块或函数发送命令,然后重新加入主进程。

多重处理还支持通过队列或管道共享变量。 它还具有一个Lock对象,用于锁定主进程中的对象以从其他进程进行写入。

多重处理有1个主要缺陷。 它在时间和内存使用上都有大量开销。 即使没有无站点,CPython的启动时间也是100-200ms(请参阅https://hackernoon.com/which-is-the-fastest-version-of-python-2ae7c61a6b2b )。

因此,您可以在CPython中使用并发代码,但必须仔细计划长时间运行的进程的应用程序 ,这些进程之间几乎没有对象共享。

另一种选择是第三方程序包,如Twisted。

PEP554和GIL的死亡?

综上所述,CPython中的多线程很容易,但是它并不是真正的并发,多处理是并发的,但是开销却很大。

如果有更好的方法怎么办?

绕过GIL的线索就是名字,全局解释器锁是全局解释器状态的一部分。 CPython进程可以具有多个解释器,因此可以具有多个锁, 但是 ,此功能很少使用,因为它仅通过C-API公开。

为CPython 3.8提议的功能之一是PEP554,子解释器的实现和标准库中带有新解释器模块的API。

这样一来,就可以从Python创建多个解释器。 Python 3.8的另一个变化是,解释器都将具有单独的GIL-

由于解释器状态包含内存分配区域,所有指向Python对象的指针的集合(本地和全局),因此PEP 554中的子解释器无法访问其他解释器的全局变量。

与多处理类似,在解释器之间共享对象的方法是序列化它们并使用一种IPC形式(网络,磁盘或共享内存)。 有许多方法可以在Python中序列化对象,包括marshal模块,pickle模块以及更标准化的方法,例如json和simplexml。 这些每个都有优点和缺点, 它们都有开销。

一等奖将是拥有一个共享的存储空间,该存储空间是可变的,并由拥有过程控制。 这样,对象可以从主解释器发送并由其他解释器接收。 这将是每个解释器都可以访问的PyObject指针的查找管理内存空间,主要过程控制锁。

API仍在制定中,但可能看起来像这样:

此示例使用numpy并通过使用marshal模块对其进行序列化在通道上发送numpy数组,然后子解释器处理数据(在单独的GIL上),因此这可能是CPU绑定的并发问题,非常适合子解释器。

效率低下

封送模块相当快,但不如直接从内存中共享对象快。

PEP 574提出了一个新的pickle协议(v5),该协议支持允许将内存缓冲区与剩余的pickle流分开处理。 对于大型数据对象,一次性将它们全部序列化并从子解释器反序列化将增加很多开销。

新的API可以这样连接( 假设尚未合并)

那肯定看起来像很多样板

好的,所以此示例使用低级子解释器API。 如果您使用了多处理库,您将认识到一些问题。 它不像线程那样简单,您不能仅仅说在单独的解释器中使用此输入列表运行此函数。

合并此PEP后,我希望我们会看到PyPi中的其他一些API也采用了它们。

子解释器有多少开销?

简短答案 :多于一个线程,少于一个进程。

长答案 :解释器具有其自己的状态,因此尽管PEP554将使创建子解释器变得容易,但它需要克隆和初始化以下内容:

  • __main__名称空间和importlib中的模块
  • 包含的sys字典
  • 内置函数(print(),assert等)
  • 线程数
  • 核心配置

可以从内存中轻松克隆核心配置,但是导入的模块并不是那么简单。 在Python中导入模块的速度很慢,因此,如果创建子解释器意味着每次都将模块导入另一个名称空间,则收益会减少。

那异步呢?

标准库中asyncio事件循环的现有实现创建了要评估的帧,但在主解释器中共享状态(因此共享GIL)。

PEP554已经经过合并,可能在Python 3.9,备选事件循环的实现,可以实现(尽管没有人那么做),其运行的异步子口译中的方法,因此,兼任。

听起来不错,请发货!

好吧,不完全是。

由于CPython已经使用单个解释器实现了很长时间,因此代码库的许多部分使用“运行时状态”而不是“解释器状态”,因此,如果要以当前形式合并PEP554,仍然会有很多问题。

例如&#xff0c;垃圾收集器&#xff08;在3.7 <中&#xff09;状态属于运行时。

在PyCon冲刺期间&#xff0c; 更改已开始将垃圾收集器状态移至解释器&#xff0c;以便每个子解释器将拥有自己的GC&#xff08;应有&#xff09;。

另一个问题是CPython代码库和许多C扩展中存在一些“全局”变量。 因此&#xff0c;当人们突然开始编写正确的并发代码时&#xff0c;我们可能会开始看到一些问题。

另一个问题是文件句柄属于该过程&#xff0c;因此&#xff0c;如果您打开了要在一个解释器中写入的文件&#xff0c;则子解释器将无法访问该文件&#xff08;无需对CPython进行进一步更改&#xff09;。

简而言之&#xff0c;还有许多其他事情需要解决。

结论&#xff1a;GIL死了吗&#xff1f;

对于单线程应用程序&#xff0c;GIL将仍然存在。 因此&#xff0c;即使在合并PEP554时&#xff0c;如果您具有单线程代码&#xff0c;也不会突然并发执行。

如果您想要Python 3.8中的并发代码&#xff0c;则遇到CPU约束的并发问题&#xff0c;那么这可能就是问题所在&#xff01;

什么时候&#xff1f;

Pickle v5和用于多处理的共享内存可能是Python 3.8&#xff08;2019年10月&#xff09;&#xff0c;子解释器将在3.8和3.9之间。

如果您现在想玩我的示例&#xff0c;我已经构建了一个自定义分支&#xff0c;其中包含所有必需的代码https://github.com/tonybaloney/cpython/tree/subinterpreters

From: https://hackernoon.com/has-the-python-gil-been-slain-9440d28fa93d



推荐阅读
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 这篇文章主要介绍了Python拼接字符串的七种方式,包括使用%、format()、join()、f-string等方法。每种方法都有其特点和限制,通过本文的介绍可以帮助读者更好地理解和运用字符串拼接的技巧。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了软件测试知识点之数据库压力测试方法小结相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 本文介绍了基于c语言的mcs51单片机定时器计数器的应用教程,包括定时器的设置和计数方法,以及中断函数的使用。同时介绍了定时器应用的举例,包括定时器中断函数的编写和频率值的计算方法。主函数中设置了T0模式和T1计数的初值,并开启了T0和T1的中断,最后启动了CPU中断。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
  • MATLAB函数重名问题解决方法及数据导入导出操作详解
    本文介绍了解决MATLAB函数重名的方法,并详细讲解了数据导入和导出的操作。包括使用菜单导入数据、在工作区直接新建变量、粘贴数据到.m文件或.txt文件并用load命令调用、使用save命令导出数据等方法。同时还介绍了使用dlmread函数调用数据的方法。通过本文的内容,读者可以更好地处理MATLAB中的函数重名问题,并掌握数据导入导出的各种操作。 ... [详细]
  • RouterOS 5.16软路由安装图解教程
    本文介绍了如何安装RouterOS 5.16软路由系统,包括系统要求、安装步骤和登录方式。同时提供了详细的图解教程,方便读者进行操作。 ... [详细]
  • 本文介绍了在Python张量流中使用make_merged_spec()方法合并设备规格对象的方法和语法,以及参数和返回值的说明,并提供了一个示例代码。 ... [详细]
author-avatar
手机用户2502939381
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有