5

我读过PyPy——它怎么可能打败 CPython?和无数其他的东西,但我无法理解用 Python 编写的东西如何比 Python 本身更快。

我能想到的唯一方法是 PyPy 以某种方式绕过 C 并直接编译成汇编语言指令。如果是这样的话,那就没问题了。

有人可以向我解释 PyPy 是如何工作的吗?我需要一个简单的答案。

我喜欢 python 并想开始贡献。无论他们是否拉取我的代码,PyPy 看起来都是一个很棒的起点。但我无法从我所做的简短研究中理解。

4

4 回答 4

14

理解 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 能力添加到它编译的程序中)。

于 2012-09-30T02:36:08.030 回答
7

“它有 JIT”的答案在技术上是正确的,但还不够。PyPy 作为 Python 代码运行,通过 Python 解释器,可以 JIT 编译它解释的 Python 代码(事实上,JIT 测试经常以这种方式运行)但仍然非常慢(开始解释可能需要几分钟)。

缺失的部分早于 JIT 并且实际上是 JIT 所必需的,它是在 Python 的受限子集(称为 RPython)中编写解释器,然后将其编译为 C 代码。这样,您将获得一个运行在大致 C 抽象级别的程序(尽管被编写为更高的抽象级别)。这个解释器在历史上一直,AFAIK 仍然比 CPython 慢一些,但不会慢几个数量级(就像解释器那样)。

您对“直接编译为汇编”的评论暴露了混乱。汇编代码不会自动比 C 代码快——事实上,你很难在生成汇编代码方面击败当今的 C 编译器,而且 C 代码更容易编写和/或生成,即使没有进入整个可移植性混乱。问题不在于将 Python 转换为 C 或汇编(看看 Nuitka),问题在于以更有效的方式解释程序而不影响语义。直接进行汇编并不能解决任何困难的问题,使为更高效的程序生成代码的相对简单的问题变得更加困难,并且很少允许您无法在 C 中表达的任何优化。

现在,PyPy 的 JIT 确实会生成机器代码,但 PyPy 可执行文件是由 C 编译器从 C 代码编译的。如果 PyPy 开发人员试图在单个平台上与现有的 C 编译器竞争,他们将是白痴,更不用说多个平台了。幸运的是,他们不是白痴并且知道这一点。让 JIT 生成汇编代码的原因是不同的,而且要好得多(对于初学者,在 JIT 的上下文中,有一些您不能在 C 中进行的优化)。

顺便说一句,我上面写的大部分内容也在您链接到的问题的答案中说明。

于 2012-09-29T19:38:09.947 回答
2

Pypy 有 JIT (Just In Time) 编译。JIT 编译可以在运行时进行优化(因为它不是预编译的)。

代码不会从一开始就编译为汇编或 C。它是解释代码(在 Pypy 解释器中运行)。然后解释器可以“即时”进行编译。

http://en.wikipedia.org/wiki/Just-in-time_compilation

http://en.wikipedia.org/wiki/Interpreted_language

于 2012-09-28T18:34:32.347 回答
2

PyPy 本身是用 RPython 编写的,它是 Python 的一个受限子集。虽然您可以在 CPython 之上运行它,但它非常慢,因此您可以将这个 RPython 翻译成 C,从而绕过解释。从理论上讲,这已经可以比 CPython 快,但实际上要慢很多。除此之外,还实现了一个即时编译器(也在 RPython 中),它将 Python 编译为汇编程序。

简而言之,在运行时的任何时间点都不涉及实际的双重解释,因此没有问题。

于 2012-09-29T23:52:13.970 回答