乐趣区

关于python:这一次Python-真的有望告别-GIL-锁了

Python 中有一把驰名的锁——全局解释器锁(Global Interpreter Lock,简写 GIL),它的作用是避免多个本地线程同时执行 Python 字节码,这会导致 Python 无奈实现真正的多线程执行。(注:本文中 Python 解释器特指 CPython)

这把锁在 Python 的晚期倒退中具备踊跃的作用(单核 CPU 时代),然而,它妨碍了 Python 在多核 CPU 上的并行编程,引起了开发者们一劳永逸的诟病。

GIL 影响的次要是 CPU 密集型工作,比方科学计算与数值计算工作。

在最近公布的 PEP-703 中,它概括了 GIL 对科学计算(次要是 AI/ML)造成的四类问题:

  • GIL 导致许多并行化操作难以表白(影响强化学习、DeepMind、医学医治及生物钻研等畛域)
  • GIL 影响了 Python 库的可用性(例如 PyTorch、scikit-learn、NumPy)
  • GIL 导致无奈充分利用 GPU 资源(例如计算机视觉工作)
  • GIL 导致难以部署 Python AI 模型(例如基于神经网络的 AI 模型)

社区中想要移除 GIL 的呼声以及尝试,此起彼伏,绵绵不绝,但这个话题始终悬而未决。

埋怨、质疑、不满、不甘、期盼等这些诸多的情绪,不是那么容易平息的。然而,从一个积重已久的宏大的我的项目中移除一个根基性的设计,又谈何容易?

2023 新年刚过,这个话题又一次热了起来,又一轮对 GIL 的挑战开始了。

这一次,事件仿佛有了新的转折,这次兴许能胜利了呢?

PEP-703 在往年 1 月 9 日新鲜出炉,尽管它目前仍是“草案”状态未被驳回,然而这份 PEP 的意义非常重大!

(注:每个 Python 学习者都应该根本理解 PEP,倡议浏览《学习 Python,怎能不懂点 PEP 呢?》)

这个 PEP 的作者是 Sam Gross,他是 nogil 我的项目的作者。Python 猫的老读者应该有印象,咱们在 2021 年曾翻译过他与 Python 外围开发者们的一次研讨会的纪要,这份纪要里概括了 nogil 的次要设计思路,同时答复了外围开发者们最为关注的约 20 个问题。

通过一年多工夫的积淀,nogil 我的项目当初终于造成了正式的 PEP,这意味着它被驳回进 Python 主分支的可能性变大了一些啦!

PEP 的题目是《使 CPython 的 GIL 成为可选项》(Making the Global Interpreter Lock Optional in CPython),内容详实,注释超过 1 万字,这个体量的 PEP 相对够得上排在所有 PEP 的前十了。

简略而言,这份提案提议给 CPython 减少一个构建时配置项 --disable-gil,作用是构建出一个线程平安的无 GIL 的解释器。

为了实现无 GIL 的解释器,Python 底层的局部设计必须作出变更,内容能够概括成四类:

  • 援用计数
  • 内存治理
  • 容器线程平安
  • 锁和原子 API

如果这份 PEP 被驳回实现的话,它会带来一个不容忽视的问题:Python 将公布两个不同版本的解释器,而第三方库也要相应地开发 / 保护 / 公布两个版本的软件包。

PEP-703 的作者也思考到了这个问题,他提出的解决方案是与 Anaconda 一起公布无 GIL 的 Python,同时在 conda 里集中公布治理那些兼容了新 Python 的库。

思考到 Anaconda 在科学计算与数值计算畛域的弱小影响力,此举既能较好地施展 nogil Python 的用途,又能缩小用户及三方库开发者面对两种发行版时的割裂感。

值得注意的是,nogil 的 Python 还有一个更大的问题,那就是会影响单线程程序的性能。

基于 Python 3.11 版本,实现了有偏见的援用计数及永生对象后,Python 单线程性能会变慢 10%。

只管这个数值在最新的 nogil 原型版本上能够升高到 5%,然而,另外至多还有两项难以躲避的性能降落点:

  • 2% – 全局的自在列表(次要是元组和浮点数自在列表)
  • 1.5% – 汇合中每个对象的互斥锁(字典、列表、队列)

单线程的代码才是最宽泛的应用场景,能够说这会影响到每一个 Python 用户。任何试图移除 GIL 的我的项目都不可避免要面临这项挑战。

只管存在着以上的两大问题,但 PEP-703 还是很有可取之处的。

比方,相比于 2015 年提出的驰名的 Gilectomy 我的项目(由 GIL ectomy 两个单词组合而成,ectomy 是一个医学上的术语“切除术”),nogil 在单线程的性能上要快得多,同时可扩展性也更好。

比方,相比于 2021 年炽热的“香农打算”的作者 Eric Snow 提出的 PEP-684 计划(给每个子解释器创立 GIL),后者一方面须要实现作为前提的多个 PEP(如 PEP-554、PEP-683),另一方面须要用户解决多子解释器间共享变量的麻烦。

在香农打算的《Python 3.12 指标》中,PEP-554 与 PEP-684 曾经囊括在内了,版本指标是充分利用 Python 的子解释器,让子解释器应用各自的 GIL,从而实现多线程的并行。

好消息是,3.12 的打算跟本文的配角 PEP-703 并不抵触。事实上,它们的很多设计细节是统一的,也就是说,这两套对于 GIL 的革新计划是能够共存的,它们相互促进,事倍功半!

香农打算有 Python 之父 Guido van Rossum 站台,还有财大气粗的微软反对着一支奢华的团队投入开发(含 Guido 和 Eric Snow),因而,多解释器多 GIL 的计划很可能会更快落地。

而 PEP-703 有 PSF 首位全职开发者 Łukasz Langa 的倾力反对,社区的反应也不错,我感觉它今后落地的心愿也挺大!

无论如何,这次香农打算和 PEP-703 掀起的对 GIL 的挑战,比以往所有的尝试都更剧烈,更有胜利的可能,让人不由得心生欢喜之喜~~

但愿它们实现的一天不会太远吧。

最初,感激浏览,如果你喜爱本文,请肯定要点赞 / 分享反对哈~

退出移动版