CPython 中的全局解释器锁 (GIL) 是什么?

2024-11-25 08:49:00
admin
原创
169
摘要:问题描述:什么是全局解释器锁?为什么它是一个问题?关于从 Python 中删除 GIL 的争论已经很多,我想了解为什么这如此重要。我自己从未编写过编译器或解释器,所以不要吝惜细节,我可能需要它们来理解。解决方案 1:Python 的 GIL 旨在序列化从不同线程对解释器内部的访问。在多核系统上,这意味着多个线...

问题描述:

什么是全局解释器锁?为什么它是一个问题?

关于从 Python 中删除 GIL 的争论已经很多,我想了解为什么这如此重要。我自己从未编写过编译器或解释器,所以不要吝惜细节,我可能需要它们来理解。


解决方案 1:

Python 的 GIL 旨在序列化从不同线程对解释器内部的访问。在多核系统上,这意味着多个线程无法有效利用多个内核。(如果 GIL 没有导致这个问题,大多数人就不会关心 GIL - 它之所以被提出来只是因为多核系统越来越流行。)如果您想详细了解它,可以观看此视频或查看这组幻灯片。信息量可能太多了,但您确实要求提供详细信息 :-)

请注意,Python 的 GIL 实际上只是 CPython(参考实现)的问题。Jython 和 IronPython 没有 GIL。作为 Python 开发人员,除非您正在编写 C 扩展,否则您通常不会遇到 GIL。C 扩展编写者需要在其扩展执行阻塞 I/O 时释放 GIL,以便 Python 进程中的其他线程有机会运行。

解决方案 2:

假设您有多个线程,它们实际上并不接触彼此的数据。这些线程应该尽可能独立执行。如果您有一个“全局锁”,需要获取它才能(比如说)调用某个函数,那么这可能会成为瓶颈。一开始,您可能不会从拥有多个线程中获得太多好处。

用现实世界来类比:想象一下,一家公司有 100 名开发人员,但只有一个咖啡杯。大多数开发人员会花时间等待咖啡,而不是编码。

这些都不是 Python 独有的——我一开始就不知道 Python 需要 GIL 的具体用途。不过,希望它能让你更好地了解一般概念。

解决方案 3:

我们先来了解一下python GIL提供了什么:

任何操作/指令都在解释器中执行。GIL 确保解释器在特定时刻由单个线程持有。并且具有多个线程的 Python 程序在单个解释器中运行。在任何特定时刻,此解释器都由单个线程持有。这意味着在任何时刻,只有持有解释器的线程在运行

那么为什么这是一个问题:

您的机器可能有多个内核/处理器。多个内核允许多个线程同时执行,即多个线程可以在任何特定时刻执行。但由于解释器由单个线程控制,因此其他线程即使可以访问内核也不会执行任何操作。因此,您无法获得多核带来的任何优势,因为在任何时刻都只有一个内核被使用,即当前控制解释器的线程正在使用的核心。因此,您的程序将像单线程程序一样花费很长时间来执行。

但是,潜在的阻塞或长时间运行的操作(例如 I/O、图像处理和 NumPy 数字运算)发生在 GIL 之外。摘自此处。因此,对于此类操作,尽管存在 GIL,多线程操作仍将比单线程操作更快。因此,GIL 并不总是瓶颈。

编辑:GIL 是 CPython 的一个实现细节。IronPython 和 Jython 没有 GIL,因此在它们中应该可以实现真正的多线程程序,不过我从未使用过 PyPy 和 Jython,对此也不太确定。

解决方案 4:

Python 3.7 文档

我还想强调一下Pythonthreading文档中的以下引文:

CPython 实现细节:在 CPython 中,由于存在全局解释器锁,因此一次只能有一个线程执行 Python 代码(尽管某些性能导向型库可能会克服此限制)。如果您希望应用程序更好地利用多核机器的计算资源,建议您使用multiprocessingconcurrent.futures.ProcessPoolExecutor。但是,如果您想同时运行多个 I/O 密集型任务,线程仍然是一个合适的模型。

这链接到词汇表条目global interpreter lock,其中解释了 GIL 意味着 Python 中的线程并行不适合CPU 密集型任务:

CPython 解释器使用的机制,用于确保一次只有一个线程执行 Python 字节码。通过使对象模型(包括关键内置类型,如 dict)隐式安全地防止并发访问,这简化了 CPython 实现。锁定整个解释器使解释器更容易实现多线程,但代价是多处理器机器所能提供的大部分并行性。

但是,一些扩展模块(无论是标准模块还是第三方模块)的设计使得在执行压缩或散列等计算密集型任务时释放 GIL。此外,执行 I/O 时始终会释放 GIL。

过去创建“自由线程”解释器(以更精细的粒度锁定共享数据的解释器)的努力没有成功,因为在常见的单处理器情况下性能会受到影响。人们认为,克服这一性能问题将使实现变得更加复杂,因此维护成本更高。

这句话还暗示,作为 CPython 实现细节,字典以及变量赋值也是线程安全的:

  • Python 变量赋值是原子的吗?

  • Python 词典中的线程安全

接下来,该包的文档multiprocessing解释了它如何通过生成进程并公开类似于的接口来克服 GIL threading

multiprocessing 是一个支持使用类似于 threading 模块的 API 生成进程的软件包。multiprocessing 软件包提供本地和远程并发,通过使用子进程而不是线程有效地避开了全局解释器锁。因此,multiprocessing 模块允许程序员充分利用给定机器上的多个处理器。它可以在 Unix 和 Windows 上运行。

并且文档concurrent.futures.ProcessPoolExecutor解释了它用作multiprocessing后端:

ProcessPoolExecutor 类是 Executor 的子类,它使用进程池来异步执行调用。ProcessPoolExecutor 使用多处理模块,这使其能够避开全局解释器锁,但也意味着只能执行和返回可 picklable 对象。

这与使用线程而不是进程的ThreadPoolExecutor其他基类形成对比

ThreadPoolExecutor 是 Executor 的子类,它使用线程池来异步执行调用。

由此我们得出结论,它只ThreadPoolExecutor适合 I/O 密集型任务,同时ProcessPoolExecutor也可以处理 CPU 密集型任务。

进程与线程实验

在多处理与线程 Python中,我对 Python 中的进程与线程进行了实验分析。

快速预览结果:

在此处输入图片描述

其他语言

这个概念似乎也存在于 Python 之外,同样适用于 Ruby,例如:https://en.wikipedia.org/wiki/Global_interpreter_lock

它提到了以下优点:

  • 提高单线程程序的速度(不需要分别获取或释放所有数据结构的锁),

  • 轻松集成通常非线程安全的 C 库,

  • 易于实现(单个 GIL 比无锁解释器或使用细粒度锁的解释器更容易实现)。

但是 JVM 似乎在没有 GIL 的情况下也能很好地工作,所以我想知道它是否值得。以下问题是 GIL 存在的原因:为什么要有全局解释器锁?

解决方案 5:

Python 不支持真正意义上的多线程。它有一个多线程包,但是如果你想要使用多线程来加快代码速度,那么使用它通常不是一个好主意。Python 有一个称为全局解释器锁 (GIL) 的构造。

https://www.youtube.com/watch?v=ph374fJqFPE

GIL 确保一次只能执行一个“线程”。一个线程获取 GIL,执行一些工作,然后将 GIL 传递给下一个线程。这个过程发生得非常快,所以在人眼看来,您的线程似乎在并行执行,但实际上它们只是轮流使用同一个 CPU 核心。所有这些 GIL 传递都会增加执行开销。这意味着,如果您想让代码运行得更快,那么使用线程包通常不是一个好主意。

使用 Python 的线程包是有原因的。如果你想同时运行一些任务,并且效率不是问题,那么它完全没问题,而且很方便。或者,如果你正在运行需要等待某些任务(例如某些 IO)的代码,那么它可能很有意义。但是线程库不会让你使用额外的 CPU 核心。

多线程可以外包给操作系统(通过执行多处理)、调用 Python 代码的某些外部应用程序(例如 Spark 或 Hadoop)或 Python 代码调用的某些代码(例如:您可以让 Python 代码调用执行昂贵的多线程操作的 C 函数)。

解决方案 6:

每当两个线程访问同一个变量时,就会出现问题。例如,在 C++ 中,避免此问题的方法是定义一些互斥锁,以防止两个线程同时进入某个对象的设置器。

Python 中可以实现多线程,但两个线程无法同时执行,粒度不能小于一条 Python 指令。正在运行的线程正在获取一个称为 GIL 的全局锁。

这意味着如果你开始编写一些多线程代码以利用多核处理器,你的性能将不会提高。通常的解决方法是使用多进程。

请注意,如果您处于用 C 编写的方法中,则可以释放 GIL。

GIL 的使用不是 Python 所固有的,而是它的一些解释器所固有的,包括最常见的 CPython。(#edited,见评论)

GIL 问题在 Python 3000 中仍然存在。

解决方案 7:

为什么 Python(CPython 和其他)使用 GIL

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

在 CPython 中,全局解释器锁(GIL)是一个互斥锁,用于阻止多个本机线程同时执行 Python 字节码。此锁是必需的,主要是因为 CPython 的内存管理不是线程安全的。

如何从 Python 中删除它?

像Lua一样,也许Python可以启动多个VM,但是python没有这样做,我猜应该还有其他原因。

在Numpy或者其他python扩展库中,有时候将GIL释放到其他线程可以提高整个程序的效率。

解决方案 8:

我想分享一个来自《视觉效果的多线程》一书的例子。这是一个典型的死锁情况

static void MyCallback(const Context &context){
Auto<Lock> lock(GetMyMutexFromContext(context));
...
EvalMyPythonString(str); //A function that takes the GIL
...    
}

现在考虑导致死锁的序列事件。

╔═══╦════════════════════════════════════════╦══════════════════════════════════════╗
║   ║ Main Thread                            ║ Other Thread                         ║
╠═══╬════════════════════════════════════════╬══════════════════════════════════════╣
║ 1 ║ Python Command acquires GIL            ║ Work started                         ║
║ 2 ║ Computation requested                  ║ MyCallback runs and acquires MyMutex ║
║ 3 ║                                        ║ MyCallback now waits for GIL         ║
║ 4 ║ MyCallback runs and waits for MyMutex  ║ waiting for GIL                      ║
╚═══╩════════════════════════════════════════╩══════════════════════════════════════╝
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用