如果PyPy快6.3倍,为什么我不应该使用PyPy而不是CPython?

我听到了很多关于pypy项目的消息。他们声称它比他们的网站上的CPython解释器快6.3倍。

每当我们谈论像Python这样的动态语言时,速度都是首要问题之一。为了解决这个问题,他们说PyPy快6.3倍。

第二个问题是并行性,臭名昭著的全局解释器锁(GIL)。为此,PyPy说它可以给没有GIL的Python

如果PyPy可以解决这些巨大的挑战,那么它的弱点是什么阻止了更广泛的采用?也就是说,是什么阻止了像我这样的典型Python开发人员切换到PyPy现在

201606 次浏览

因为pypy不是100%兼容的,需要8 gigs的内存来编译,是一个移动的目标,并且是高度实验性的,其中cpython是稳定的,是模块构建者20年来的默认目标(包括在pypy上不起作用的c扩展),并且已经广泛部署。

Pypy可能永远不会成为参考实现,但它是一个很好的工具。

第二个问题更容易回答:如果你所有的代码都是纯Python,你基本上可以使用PyPy作为一个直接的替代品。然而,许多广泛使用的库(包括一些标准库)是用C编写的,并作为Python扩展编译的。其中一些可以与PyPy一起使用,有些不能。PyPy提供了与Python相同的“前向”工具——也就是说,它是Python——但它的内部结构不同,因此与这些内部结构交互的工具将无法工作。

至于第一个问题,我想这有点像Catch-22:PyPy一直在快速发展,以提高速度并增强与其他代码的互操作性。这使得它比官方更具实验性。

我认为如果PyPy进入稳定状态,它可能会开始得到更广泛的使用。我也认为Python摆脱其C基础会很好。但这不会发生一段时间。PyPy还没有达到临界质量,它本身几乎足够有用,可以做你想做的一切,这将激励人们填补空白。

注:与2013年提出此问题时相比,PyPy现在更成熟,支持也更好。避免从过时的信息中得出结论。


  1. 正如其他人很快提到的那样,PyPy对C扩展的支持很弱。它有支持,但通常速度比Python慢,充其量是不确定的。因此,很多模块只需要CPython。PyPy不支持numpy。一些扩展仍然不受支持(熊猫SciPy等),在进行更改之前请查看支持的包列表请注意,现在支持列表中标记为不支持的许多包。
  2. Python 3支持目前是实验性的。刚刚达到稳定!截至2014年6月20日,PyPy3 2.3.1-支点出来了
  3. 对于“脚本”,PyPy有时实际上并不更快,很多人使用Python。这些是运行时间短的程序,它们做一些简单而小的事情。因为PyPy是一个即时编译器,它的主要优势来自长运行时间和简单的类型(例如数字)。与CPython相比,PyPy的JIT前速度可能很差。
  4. 惯性.迁移到PyPy通常需要重新调整工具,这对一些人和组织来说简直是太多的工作。

这些是影响我的主要原因,我会说。

我就这个话题做了一个小基准测试。虽然许多其他海报都对兼容性提出了很好的观点,但我的经验是,PyPy对于只是移动位来说并没有那么快。对于Python的许多用途,它实际上只存在于两个或多个服务之间的位转换。例如,没有多少网络应用程序对数据集执行CPU密集型分析。相反,它们从客户端获取一些字节,将它们存储在某种数据库中,然后将它们返回给其他客户端。有时数据的格式会改变。

BDFL和CPython开发人员是一群非常聪明的人,他们设法帮助CPython在这种情况下表现出色。这是一个无耻的博客插件:http://www.hydrogen18.com/blog/unpickling-buffers.html。我正在使用Stackless,它源自CPython并保留了完整的C模块接口。在这种情况下,我没有发现使用PyPy有任何优势。

该网站没有声称PyPy比CPython快6.3倍。引用:

所有基准的几何平均值比CPython快0.16或6.3倍

这是一个与你所做的总括性陈述完全不同的陈述,当你理解了其中的区别,你至少会理解为什么你不能只说“使用PyPy”的一组原因。这听起来像是我在吹毛求疵,但理解为什么这两个陈述完全不同是至关重要的。

为了打破它:

  • 他们所做的陈述只适用于他们所使用的基准测试。它绝对没有说明您的程序(除非您的程序与他们的基准测试完全相同)。

  • 该声明是关于一组基准测试的<强>平均值。没有人声称运行PyPy会带来6.3倍的改进,即使对于他们已经测试过的程序也是如此。

  • 没有人声称PyPy甚至会运行CPython运行<强>的所有程序,更不用说更快了。

CPython有引用计数和垃圾回收机制,PyPy只有垃圾回收机制。

因此,对象往往会更早被删除,并且在CPython中以更可预测的方式调用__del__。一些软件依赖于这种行为,因此它们还没有准备好迁移到PyPy。

其他一些软件可以同时使用两者,但使用CPython时使用的内存较少,因为未使用的对象会更早释放。(我没有任何测量来表明这有多重要,以及其他哪些实现细节会影响内存使用。)

对于很多项目来说,不同的蟒蛇在速度方面实际上有0%的差异。这是那些由工程时间主导的项目,所有蟒蛇都有相同数量的库支持。

问:如果与CPython相比,PyPy可以解决这些巨大的挑战(速度、内存消耗、并行性),那么它的弱点是什么?

答:首先,几乎没有证据表明PyPy团队可以解决速度问题一般。长期的证据表明PyPy运行某些Python代码比CPython慢,这个缺点似乎深深植根于PyPy。

其次,当前版本的PyPy在相当大的情况下消耗的内存比CPython多得多。所以PyPy还没有解决内存消耗问题。

PyPy能否解决上述巨大挑战,以及一般是否会比CPython更快、内存消耗更少、对并行更友好,这是一个短期内无法解决的悬而未决的问题。有人打赌PyPy永远无法提供一般的解决方案,使其在所有情况下都主导CPython 2.7和3.3。

如果PyPy成功地优于CPython,这是值得怀疑的,那么影响其更广泛采用的主要弱点将是它与CPython的兼容性。还存在一些问题,例如CPython在更广泛的CPU和操作系统上运行,但与PyPy的性能和CPython兼容性目标相比,这些问题要重要得多。


问:为什么我现在不能用PyPy替换CPython?

答:PyPy与CPython不是100%兼容,因为它没有在幕后模拟CPython。某些程序可能仍然依赖于CPython的独特功能,这些功能在PyPy中没有,例如C绑定、Python对象和方法的C实现或CPython垃圾收集器的增量性质。

简单来说:PyPy提供了CPython所缺乏的速度,但牺牲了其兼容性。然而,大多数人选择Python是因为它的灵活性和“包含电池”的特性(高兼容性),而不是因为它的速度(尽管它仍然是首选)。

我发现了一些例子,其中PyPy比Python慢。但是:只有在Windows上。

C:\Users\User>python -m timeit -n10 -s"from sympy import isprime" "isprime(2**521-1);isprime(2**1279-1)"10 loops, best of 3: 294 msec per loop
C:\Users\User>pypy -m timeit -n10 -s"from sympy import isprime" "isprime(2**521-1);isprime(2**1279-1)"10 loops, best of 3: 1.33 sec per loop

所以,如果你想到PyPy,请忘记Windows。在Linux,你可以获得惊人的加速度。示例(列出1到1,000,000之间的所有素数):

from sympy import sieveprimes = list(sieve.primerange(1, 10**6))

这在PyPy上的运行速度比在Python上快10(!)倍。但不是在Windows上。它只有3倍的速度。

PyPy支持Python 3已经有一段时间了,但根据这个HackerNoon post by Anthony Shaw四月2,2018,PyPy3仍然比PyPy(Python 2)慢几倍。

对于许多科学计算,特别是矩阵计算,numpy是更好的选择(参见常见问题:我应该安装numpy还是numpypy?)。

Pypy不支持gmpy2。您可以使用gmpy_cffi,尽管我还没有测试它的速度,并且该项目在2014年发布了一个版本。

对于Project Euler问题,我经常使用PyPy,对于简单的数值计算,通常from __future__ import division就足以满足我的目的,但截至2018年,Python 3支持仍在开发中,您最好的选择是64位Linux。

支持的Python版本

引用Python之禅

可读性很重要。

例如,Python 3.8引入了fstring=

Python 3.8+中可能还有其他对您更重要的功能。PyPy目前不支持Python 3.8+。

无耻的自我广告:Python版本的杀手功能-如果你想知道更多你使用旧Python版本错过的东西