PyPy —如何击败CPython?


264

来自Google开源博客

PyPy是Python中Python的重新实现,它使用先进的技术来尝试获得比CPython更好的性能。多年的努力终于有了回报。我们的速度结果通常要比CPython好,从稍慢一些到实际应用程序代码的速度提高2倍,再到小型基准测试的速度提高10倍。

这怎么可能?哪个Python实现用于实现PyPy?CPython的?PyPyPy或PyPyPyPy击败他们的分数的机会是什么?

(在相关说明中……为什么有人会尝试这样的方法?)


43
Nitpick:PyPy PyPyPy。将Py- *前缀视为投影算符。
u0b34a0f6ae 2010年

好。所以PyPy应该比CPython更受青睐?它有什么缺点吗?
balki 2012年

10
PyPy在运行时优化方面非常出色,但是其不同的内在特性使其与几种流行的C扩展不兼容
Cees Timmerman 2012年

4
几乎每个人都缺少关于理论上如何提高速度的问题。但是请考虑一下:Python可以做任何事情,就像图灵机一样。gcc毕竟它可以调用。因此,您还可以编写一些在CPython上运行的python代码,该python代码解释一些其他python代码,将其转换为C,然后执行gcc,然后执行已编译的程序。如果经常调用该代码,它可能会更快。
osa

Answers:


155

Q1。这怎么可能?

在某些情况下,手动内存管理(这是CPython对其计数的方式)可能比自动管理要慢。

CPython解释器实现的局限性排除了PyPy可以进行的某些优化(例如,细粒度的锁)。

正如Marcelo所述,JIT。能够即时确认对象的类型可以节省您进行多个指针取消引用的操作,以最终到达您要调用的方法。

Q2。哪个Python实现用于实现PyPy?

PyPy解释器在RPython中实现,RPython是Python的静态类型子集(该语言而不是CPython解释器)。- 有关详细信息,请参阅https://pypy.readthedocs.org/en/latest/architecture.html

Q3。PyPyPy或PyPyPyPy击败他们的分数的机会是什么?

那将取决于这些假设解释器的实现。例如,如果其中一个拿到了源代码,对其进行了某种分析,并在运行了一段时间后将其直接转换为目标紧密的特定汇编代码,我想它会比CPython快得多。

更新:最近,在一个精心设计的示例中,PyPy优于使用编译的类似C程序gcc -O3。这是一个人为的案例,但确实体现了一些想法。

Q4。为什么有人会尝试这样的事情?

从官方网站。https://pypy.readthedocs.org/zh_CN/latest/architecture.html#mission-statement

我们旨在提供:

  • 一个通用的翻译和支持框架,用于生成
    动态语言的实现,强调
    语言规范和实现
    方面之间的明确区分。我们称此为RPython toolchain_。

  • Python_语言的合规,灵活和快速实现,它使用上述工具链来启用新的高级高级功能,而不必对低级细节进行编码。

通过以这种方式分离关注点,我们的Python和其他动态语言的实现能够自动为任何动态语言生成即时编译器。它还允许采用混合匹配方法来实施决策,包括许多历史上在用户控制范围之外的决策,例如目标平台,内存和线程模型,垃圾回收策略以及所应用的优化,包括是否具有首先是JIT。

C编译器gcc用C实现,Haskell编译器GHC用Haskell编写。您是否有理由不使用Python编写Python解释器/编译器?


82
这个答案完全没有关于PyPy如何快速的主要解释。虽然它提到PyPy并不是真正在Python中实现的,但是在RPython中却没有指出RPython代码是静态编译和优化的,以生成PyPy解释器(它恰好也是可以在顶部运行的有效Python代码) CPython的运行速度要慢得多)。他们在“普通Python”中实现的是RPython“编译器”(在块引用中引用的翻译框架)。
2012年

12
这掩盖了书架。大多数性能来自翻译为C(这使解释器不会比CPython慢​​很多)和JIT(使热路径更快)。
东武

4
“更新:最近,在一个精心设计的示例中,PyPy优于使用gcc -O3编译的类似C程序。” 而且,如果您阅读该帖子下的第一条评论,您将看到该帖子的作者不知道链接时优化。启用链接时间优化后,C代码运行速度更快。
阿里

2
好吧,博客文章发表于2011年,而答案在2014年发表。此外,此评论确实提到了共享库。我不知道其中多少(答案和博客文章)有效。在过去的几年中,所有涉及的技术都发生了很大的变化。
Noufal Ibrahim 2014年

1
在两个精心设计的Pypy实例比等效C更快的情况下,由于一系列非常具体的原因,每个实例在基准测试中都更快。第一个是因为Pypy足够聪明,可以实现对事物进行严格的循环计数,所以永远不会使用该计数,因此可以将其完全删除(JIT传递),第二个可以组合在一起:因为Pypy JIT可以“跨库边界内联”,因此“ printf”函数的示例专门用于字面意义上仅能够发出整数,并消除了重复的malloc(内存分配开销)。
amcgregor,

291

尽管在技术上是正确的,“ PyPy是Python在Python中的重新实现”是一种相当误导的方式来描述恕我直言的PyPy。

PyPy有两个主要部分。

  1. 翻译框架
  2. 口译员

翻译框架是编译器。它将RPython代码编译为C(或其他目标),并自动添加垃圾回收和JIT编译器等方面。它不能处理任意的Python代码,只能处理RPython。

RPython是普通Python的子集;所有RPython代码都是Python代码,但并非相反。RPython没有正式的定义,因为RPython基本上只是“可由PyPy的翻译框架翻译的Python子集”。但是要进行翻译,RPython代码必须是静态类型的(推断类型,您不必声明它们,但严格来说,它仍然是每个变量的一种类型),并且您不能执行诸如声明/修改函数/类在运行时。

然后,解释器是用RPython编写的普通Python解释器。

由于RPython代码是普通的Python代码,因此您可以在任何Python解释器上运行它。但是,PyPy的速度要求均不来自这种方式。这只是一个快速的测试周期,因为翻译解释器需要长时间。

有了这样的理解,对于PyPyPy或PyPyPyPy的猜测实际上没有任何意义。您有一个用RPython编写的解释器。您将其转换为可快速执行Python的C代码。到此过程停止;不再有RPython可以通过再次处理来加快速度。

因此“ PyPy怎么可能比CPython更快”就变得很明显。PyPy有一个更好的实现,包括一个JIT编译器(我相信,没有JIT编译器,它通常不会那么快,这意味着PyPy仅对于易受JIT编译的程序而言更快)。CPython从未被设计为Python语言的高度优化的实现(尽管您确实遵循差异,但它们确实尝试使其成为高度优化的实现)。


PyPy项目的真正创新之处在于,它们无需手动编写复杂的GC方案或JIT编译器。他们用RPython相对直接地编写解释器,并且由于所有RPython都比Python低,所以它仍然是一种面向对象的垃圾收集语言,比C高得多。然后,翻译框架自动添加GC和JIT之类的东西。所以翻译框架是一个巨大的努力,但它同样适用于PyPy python解释器,但是他们更改了实现,从而在实验中拥有更大的自由度来提高性能(而不必担心引入GC错误或更新JIT编译器以应对更改)。这也意味着当他们开始实现Python3解释器时,它将自动获得相同的好处。以及使用PyPy框架编写的任何其他解释器(其中有很多处于波兰的不同阶段)。并且所有使用PyPy框架的解释器都会自动支持该框架支持的所有平台。

因此,PyPy项目的真正好处是(尽可能)将实现动态语言的,与平台无关的高效解释器的所有部分分开。然后在一个地方提出一种很好的实现,可以在许多口译员之间重复使用。这并不是像“我的Python程序现在运行速度更快”那样的即时胜利,但它是未来的广阔前景。

而且它可以更快(也许)运行您的Python程序。


4
我无法追随差异:(
polvoazul 2013年

37
@polvoazul的之间的区别优化语言的实现和优化呢?好吧,当我说CPython是一个经过优化的实现时,我的意思是开发人员试图使解释器本身的内部算法和内置数据结构高效运行。一个优化的实现OTOH将分析最终用户代码,并尝试找出将其转换为更有效执行的方法。
2013年

23

PyPy是用Python实现的,但是它实现了JIT编译器来动态生成本机代码。

在Python之上实现PyPy的原因可能是它只是一种非常有生产力的语言,尤其是因为JIT编译器使宿主语言的性能变得无关紧要。


JIT是生成与PyPy处于同一级别运行的Python代码,还是会生成以运行PyPy的任何Python实现级别运行的真实本机代码?
Edmund

3
真正的本机代码(请参阅此处);准确地说是32位x86代码。
Marcelo Cantos

11

PyPy用受限Python编写。据我所知,它不能在CPython解释器之上运行。受限制的Python是Python语言的子集。AFAIK将PyPy解释器编译为机器代码,因此在安装时,它在运行时不使用python解释器。

您的问题似乎希望PyPy解释器在执行代码时在CPython之上运行。 编辑:是的,要使用PyPy,您首先需要将PyPy python代码转换为C并使用gcc进行编译,转换为jvm字节代码或.Net CLI代码。请参阅入门


8
PyPy将在CPython之上运行,但是在这种模式下,它无法提供人们可能想要的速度提升。:-) codespeak.net/pypy/dist/pypy/doc/...
弗兰克V
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.