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

Why shouldn't I use PyPy over CPython if PyPy is 6.3 times faster?

我听说了很多关于Pypy项目的事。他们声称这比他们网站上的cpython解释器快6.3倍。

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

第二个问题是并行性,臭名昭著的全局解释器锁(gil)。为了这个,派比说它可以给吉尔更少的Python。

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


  • 正如其他人很快提到的,Pypy对C扩展的支持很薄弱。它有支持,但通常比Python的速度慢,最好是不稳定的。因此,许多模块只需要cpython。Cython和Numpy对于数字来说是非常棒的,而大多数在Python中真正需要速度的人(熊猫、Scipy等)正在大量使用这些工具。因为它们要么不存在,要么被很小的支持,而且速度很慢,所以需要一个快速的Python的人在速度和易用性上通常都比cpython要好。
  • python 3 support目前是实验性的。刚刚达到稳定状态!截至2014年6月20日,Pypy3 2.3.1-支点已用完!
  • pypy有时候对"scripts"来说并不快,很多人使用python。这些是短时间运行的程序,可以做一些简单和小的事情。因为pypy是一个jit编译器,它的主要优点来自长运行时间和简单的类型(如数字)。坦率地说,Pypy的预抖动速度比CPython差得多。
  • 惯性。迁移到Pypy通常需要重新工具化,对于某些人和组织来说,这实在是太多的工作了。
  • 我想说,这些是影响我的主要原因。

    NOTE: This question is ancient! Avoid drawing conclusions from out-of-date information.


    该网站没有声称Pypy比CPython快6.3倍。引述:

    The geometric average of all benchmarks is 0.16 or 6.3 times faster than CPython

    这是一个非常不同的声明,你所做的总括声明,当你理解的差异,你会明白至少一套原因,为什么你不能说"使用Pypy"。这听起来好像我在吹毛求疵,但理解为什么这两种说法完全不同是至关重要的。

    要将其分解:

    • 他们的声明只适用于他们使用的基准。它完全没有提到您的程序(除非您的程序与它们的基准完全相同)。

    • 该声明是一组基准的平均值。没有人说运行pypy即使对他们测试过的程序也会有6.3倍的改进。

    • 没有人说Pypy甚至可以运行cpython运行的所有程序,更不用说运行得更快了。


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

    Pypy可能永远不会是引用实现,但它是一个很好的工具。


    第二个问题更容易回答:如果您的所有代码都是纯Python,那么您基本上可以使用pypy作为替换。然而,许多广泛使用的库(包括一些标准库)是用C语言编写的,并编译为Python扩展。其中一些可以用来和pypy一起工作,有些不能。pypy提供了与python相同的"前向"工具,也就是说,它是python,但是它的内部是不同的,因此与这些内部接口的工具无法工作。

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

    我认为,如果Pypy进入稳定状态,它可能会开始得到更广泛的应用。我还认为,对于Python来说,从它的C基础上转移出去是非常好的。但暂时不会发生。Pypy还没有达到临界质量,它本身几乎足够有用,可以做任何你想做的事情,这将激励人们填补空白。


    我在这个问题上做了一个小基准。虽然许多其他的海报在兼容性方面都做得很好,但我的经验是,Pypy并没有那么快,只需移动位。对于python的许多用途,它实际上只存在于两个或多个服务之间转换位的情况。例如,没有多少Web应用程序正在对数据集执行CPU密集型分析。相反,它们从客户机获取一些字节,将它们存储在某种数据库中,然后将它们返回到其他客户机。有时数据的格式会改变。

    bdfl和cpython开发人员是一个非常聪明的群体,他们帮助cpython在这种情况下表现出色。下面是一个不知羞耻的博客插件:http://www.hydrogen18.com/blog/unpickling-buffers.html。我使用的是Stackless,它是从CPython派生的,并保留了完整的C模块接口。在这种情况下,我没有发现使用pypy有什么好处。


    问:与cpython相比,如果pypy能够解决这些巨大的挑战(速度、内存消耗、并行性),那么它的哪些弱点阻碍了更广泛的采用?

    答:首先,几乎没有证据表明Pypy团队能够解决一般的速度问题。长期的证据表明,pypy运行某些python代码的速度比cpython慢,而且这个缺点似乎深深植根于pypy。

    其次,当前版本的pypy在相当大的一组情况下比cpython消耗更多的内存。所以Pypy还没有解决内存消耗问题。

    Pypy是否解决了上述巨大的挑战,并且通常比CPython更快、更少的内存消耗和更友好的并行性,这是一个短期内无法解决的开放性问题。有些人打赌,Pypy将永远无法提供一个通用的解决方案,使其在所有情况下都能主宰CPython2.7和3.3。

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

    问:为什么我现在不能用Pypy代替Cpython?

    答:Pypy与cpython不完全兼容,因为它不是在引擎盖下模拟cpython。有些程序可能仍然依赖于pypy中缺少的c python的独特特性,例如c绑定、python对象和方法的c实现,或者cpython垃圾收集器的增量特性。


    cpython有引用计数和垃圾收集,pypy只有垃圾收集。

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

    其他一些软件可以同时使用这两种软件,但是对cpython使用较少的内存,因为未使用的对象会更早地被释放。(我没有任何度量来指示这有多重要,以及其他实现细节对内存使用的影响。)


    我发现了一些例子,其中pypy比python慢。但是:只在窗户上。

    1
    2
    3
    4
    5
    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

    所以,如果你想到派比,就忘了窗户。在Linux上,您可以实现惊人的加速。示例(列出1到1000000之间的所有素数):

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

    这是10次!!)在pypy上比在python上快。但不在窗户上。那里的速度只有3倍。


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


    对于许多项目来说,不同的Python在速度上实际上相差0%。这是那些由工程时间主导的,所有的Python都有相同数量的图书馆支持。


    Pypy已经有一段时间支持python 3了,但是根据Anthony Shaw于2018年4月2日发布的黑客中午帖子,Pypy3仍然比Pypy(python 2)慢几倍。

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

    pypy不支持gmpy2。你可以使用gmpy-cffi,尽管我还没有测试它的速度,这个项目在2014年发布了一个版本。

    对于Project Euler问题,我经常使用pypy,对于简单的数值计算,通常from __future__ import division就足以满足我的需要,但到2018年,python 3支持仍在进行中,您最好的选择是64位Linux。Windows PYP3.5 V6.0最新版本(截至2018年12月)是试用版。