我已阅读PyPy -- How can it possibly beat CPython?以及无数其他内容,但我无法理解Python编写的内容如何比python本身更快。
我能想到的唯一方法是PyPy以某种方式绕过C并直接编译成汇编语言指令。如果是这样,那就没关系了。
有人可以向我解释PyPy的工作原理吗?我需要一个简单的答案。
我喜欢python并希望开始贡献。 PyPy看起来像一个很棒的起点,无论他们是否拉我的代码。但我无法从我所做的简短研究中理解。
答案 0 :(得分:13)
理解PyPy的最简单方法是忘记它是用Python实现的。
实际上它不是,无论如何,它是在RPython中实现的。 RPython可以使用Python解释器运行,但是Python代码不能够由RPython编译器(PyPy转换框架)编译。 RPython是Python的一个子集,但是“遗漏”的部分非常实用,RPython中的编程非常与Python中正常的编程不同。
因此,由于Python代码不能被视为RPython代码,并且惯用的RPython程序“外观和感觉”与惯用的Python程序非常不同,让我们完全忽略它们之间的联系,并考虑一个简单的例子。
假装我用编译器开发了一种新语言Frobble。我在Frobble写了一个Python解释器。我声称我的“FrobblePython”解释器通常比CPython解释器快得多。
这会让你觉得奇怪或不可能吗?当然不是。新的Python解释器可以比CPython解释器更快或更慢(或者更有可能,在某些事情上更快,在其他事情上更慢,通过改变边距)。它是否更快将取决于FrobblePython的实现,以及我的Frobble编译器编译的代码的性能特征。
完全你应该如何看待PyPy解释器。用于实现它的语言RPython碰巧能够被Python解释器解释(与编译RPython程序并运行它的外部结果相同)与理解完全无关它有多快。重要的是PyPy解释器的实现,以及RPython编译器编译的代码的性能特征(例如RPython编译器可以自动为它编译的程序添加某些类型的JITing功能)。
答案 1 :(得分:6)
"它有一个JIT"答案在技术上是正确但不充分。 PyPy作为Python代码运行,由Python解释器,JIT编译Python代码 it 解释(实际上,JIT测试通常以这种方式运行)但仍然非常慢(可能需要几分钟才能完成)只需开始解释)。
缺少的部分,在JIT之前,实际上是JIT所需的,是在Python的一个受限子集(称为RPython)中编写解释器,然后将其编译为C代码。通过这种方式,您可以获得一个大致在C抽象级别运行的程序(尽管被编写为更高级别的抽象)。这个解释器在历史上一直是,而AFAIK仍然比CPython慢一些,但速度要慢几个数量级(作为一个解释性的解释器)。
您对"直接汇编到汇编的评论"背叛混乱。汇编代码不会自动比C代码更快 - 事实上,你很难在生成汇编代码时击败今天的C编译器,并且C代码更容易编写和/或生成,甚至没有陷入整个可移植性的混乱。问题不是将Python变成C或汇编(看看Nuitka),问题是在不影响语义的情况下以更有效的方式解释程序。直接进行汇编并没有解决任何难题,使得为更高效的程序生成代码的相对容易的问题更难,并且很少允许您在C中也表达的任何优化。
现在,PyPy的JIT确实生成了机器代码,但PyPy可执行文件是由C编译器从C代码编译的。如果他们试图在一个平台上与现有的C编译器竞争,那么PyPy开发人员将是白痴,更不用说多个平台了。幸运的是,他们不是白痴,而且知道这一点。让JIT生成汇编代码的原因是不同的并且要好得多(对于初学者来说,在JIT的上下文中 你可以在C中进行几次优化)。
顺便说一下,我上面写的大部分内容也在你链接到的问题的答案中说明。
答案 2 :(得分:3)
PyPy本身是用RPython编写的,RPython是Python的一个受限子集。虽然你可以在CPython之上运行它,但速度很慢,所以你将这个RPython翻译成C语言,因此绕过了解释。理论上,这可能已经比CPython更快,但实际上相当慢。最重要的是,它实现了一个及时编译器(也在RPython中),它将Python编译为汇编程序。
简而言之,在运行期间的任何时间点都不会涉及实际的双重解释,所以没有问题。
答案 3 :(得分:2)
Pypy有JIT(及时)编译。 JIT编译可以在运行时进行优化(因为它没有预编译)。
代码不会从头开始编译为Assembly或C.它是解释代码(在Pypy解释器中运行)。然后解释器可以进行“即时”编译。