关于全局解释器锁(GIL)是一个提议,旨在解决CPython中最大的可扩展性限制——全局解释器锁(GIL)。GIL阻止了多个线程同时执行Python代码,从而影响了Python利用多核CPU的能力。全局解释器锁提出了添加一个构建配置(--disable-gil),让CPython可以在没有GIL的情况下运行Python代码,并且进行必要的改动,使得解释器线程安全。
全局解释器锁主要针对科学计算领域,特别是AI/ML领域的需求,因为这些领域需要高效地利用并行性来加速计算密集型的任务。GIL使得很多类型的并行性难以在Python中表达或实现,例如操作间、请求间等,并且给现有的并行化技术带来了很多限制(如多进程、协程等)。全局解释器锁收集了一些来自该领域专家和用户的反馈和见证,说明了GIL对他们工作和研究带来的困难和挑战。
全局解释器锁(GIL)涉及到CPython内部实现的大量改动,但对公共Python和C API的影响相对较小。主要改动包括:
- 引入偏置引用计数(biased reference counting)机制,以减少引用计数操作对原子指令(atomic instruction)和缓存一致性协议(cache coherence protocol)带来的开销。
- 引入延迟引用计数(deferred reference counting)机制,以避免在对象之间传递所有权时频繁地增加或减少引用计数。
- 引入不死对象(immortal objects)机制,以避免在某些情况下出现循环引用导致内存泄漏。
- 修改CPython内部数据结构和函数调用栈等部分,以保证线程安全。
全局解释器锁(GIL)还提出了一些API变化,包括:
- 添加Py_NOGIL宏,在编译时指示是否使用--disable-gil选项。
- 添加PyThreadState_GetInterpreter()函数,在运行时获取当前线程所属的解释器对象。
- 添加PyInterpreterState_GetMainModule()函数,在运行时获取当前解释器所属的主模块对象。
- 修改PyEval_InitThreads()函数,在没有GIL时不执行任何操作。
- 修改PyEval_RestoreThread()函数,在没有GIL时不检查当前线程是否持有GIL。
全局解释器锁(GIL)还讨论了一些可能存在或需要考虑的问题和挑战,例如:
- 性能影响:去除GIL可能会导致单线程性能下降或波动。作者提供了一些基准测试结果,并认为这种影响是可以接受或优化掉的。
- 兼容性问题:去除GIL可能会导致一些依赖于GIL特性或假设存在GIL情况下编写的扩展模块无法正常工作。作者建议使用--disable-gil选项构建CPython时,在导入这些模块时抛出异常,并鼓励扩展模块作者适配新
目前提议目前还处于草案状态,尚未被接受或拒绝。它引起了Python社区的广泛关注和讨论,有些人对它表示支持和赞赏,有些人则对它表示质疑和担忧。评价这个提议的标准可能因人而异,但一般来说,可以从以下几个方面考虑:
- 需求性:这个提议是否能够解决一个重要且普遍的问题?是否有足够多的用户和场景需要这个功能?
- 可行性:这个提议是否能够在技术上实现?是否有足够的资源和时间来完成这个工作?是否有足够的测试和验证来保证质量?
- 兼容性:这个提议是否会影响现有的代码和模块?是否会引入新的错误或安全风险?是否会导致分裂或混乱?
- 性能影响:这个提议是否会改善或恶化Python的性能?是否会带来新的优化机会或挑战?
- 一致性:这个提议是否符合Python的设计哲学和原则?是否与其他语言特性或标准保持一致?