乐趣区

关于python:与-Python-之父聊天更快的-Python

Python 猫注: 在往年 5 月的 Python 语言峰会上,Guido van Rossum 作了一场《Making CPython Faster》的分享(资料在此),宣告他退出了激动人心的“香农打算”,旨在 4 年内晋升 Python 性能至 5 倍。近日,Guido 上了一档英文播客节目(时长 30 分钟),议论了他正在做的与高性能相干的工作,解答了几个问题。播客作者整顿了一份内容纪要,本文是对该纪要的翻译。注:文末有音频及文稿下载

作者:Software at Scale

译者:豌豆花下猫 @Python 猫

原文:https://www.softwareatscale.d…

1、为什么你会对钻研 Python 的性能感兴趣?

Guido:在某种意义上,它对我来说是一个绝对难受的话题,因为这意味着与 Python 的外围打交道,而我对这方面还算相熟。当我在微软工作时,我曾短暂地关注过 Azure,但我意识到我在谷歌或 Dropbox 时就不喜爱这类工作。而后我关注了机器学习,但这须要花很多工夫来做一些与 Python 无关的事件,甚至它与 Python 相干的局部就很少。

2、Mark Shannon 对于 Python 性能的那些想法有何不同,怎么能压服你去实现它们的呢?

Guido:我喜爱他思考问题的形式。大多数其它聚焦于 Python 性能的办法,如 PyPy 和 Cinder,并不适用于所有的应用场景,因为它们不能向后兼容扩大模块。Mark 具备 CPython 开发者的视角和教训,并且有一种可行的办法来维持向后兼容性,这是最难解决的问题。Python 的字节码解释器常常要在小版本之间(例如 3.8→3.9)进行批改,起因有很多,比方新的操作码,所以批改它是一种绝对平安的计划。

3、你能给咱们解释一下 Python 解释器的分层执行的概念么?

Guido:当执行一个程序时,你不晓得它会在运行了几分之一毫秒后解体,还是会继续运行三周工夫。因为对于同一份代码,在第一种状况下,它可能触发了一个 bug。如果运行程序须要三周工夫,兴许提前半小时优化所有待运行的代码是有意义的。

但很显著,特地是在像 Python 这样的动静语言中,咱们尽可能多地做,而不要求用户通知咱们他们到底须要怎么做,你只是想尽快开始执行代码。所以,如果有一个小脚本,或者一个大程序,它碰巧执行失败了或者因为某些起因提前退出了,你就不必破费工夫去优化全副的代码了。

所以,咱们要做的就是放弃字节码编译器的简单化,以便能尽快地开始执行代码。如果有某些函数被屡次执行,那么咱们就称其为 hot 函数。“hot”存在多种定义。在某些状况下,如果一个函数被调用超过一次,或者超过两次,或者超过 10 次,那么它被定义成一个热门函数。而在其它激进的状况下,你可能说“只有被调用 1000 次才算 hot”。

而后,当参数的类型是某些特定类型时,专门化的自适应编译器(PEP-659 Specializing Adaptive Compiler)会尝试用更快的字节码来替换某些字节码。一个简略的假想的例子是 Python 中的加号运算符,它能够令很多对象相加,比方整数、字符串、列表,甚至元组。然而,你不能将整数与字符串相加。

因而,优化的办法就是提供一个独自的“两个整数相加”的字节码,它是一个对用户暗藏的第二层字节码。(“优化”通常被称为减速 quickening,但个别在咱们的语境中,咱们称之为专门化 specializing)。这个操作码假如它的两个参数都是真正的 Python 整型对象,间接读取这些对象的值,并在机器寄存器中将这些值相加,最初将后果推回堆栈。

两个整数相加的操作依然须要对参数进行类型查看。因而,它不是齐全不受约束的,但这种类型查看相比于齐全泛化的面向对象的加号操作,前者在实现上要快得多。

最初,有可能一个函数被整型参数调用了数百万次,而后忽然一小段代码用浮点型参数调用它,或者呈现更糟的状况。此时,解释器会间接执行原始的字节码。这是一个重要的局部,让你始终能失去残缺的 Python 语义。

Python 猫注:“香农打算”的最终目标是将解释器的执行过程分层,并对不同层做出定制的优化。详情请查阅 Github 我的项目的介绍(https://github.com/markshannon/faster-cpython/blob/master/tiers.md)。

4、通常你会在谈 JIT(Just-In-Time)编译器时听到这些技术,但官网 Python 当初还没有实现。

Guido:即时编译的计划有一大堆咱们想要防止的情感包袱。比方,咱们不分明到底编译什么,以及什么时候编译。在程序开始执行之前,解释器将源代码编译成字节码,而后,再将字节码转换为专门的字节码。这意味着,所有的事件都在运行时的某个时刻产生,那么,哪个局部是所谓的即时(Just-In-Time)呢?

另外,人们通常认为 JIT 会主动地使所有代码变得更好。可怜的是,你通常无奈真正地预测代码的性能。因为有古代的 CPU 和它们神奇的分支预测,咱们曾经领有了足够的性能。例如,咱们以一种本认为可能显著缩小内存拜访次数的形式,编写了一份代码。然而,当对它进行基准测试时,咱们发现它的运行速度与旧的未优化代码一样快,因为 CPU 在没有咱们任何帮忙的状况下,计算出了优化的拜访模式。我心愿我晓得古代 CPU 在分支预测和内联缓存方面做了什么,因为这就像是魔法个别。

残缺内容

以上就是播客节目纪要的翻译。更多残缺的对话内容,以及对话音频,我已保留好了。你如果感兴趣的话,请在 Python 猫 公众号里发送数字“1030”,即可获取下载链接。

退出移动版