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

chh*_*yal 660 python performance jit pypy cpython

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

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

第二个问题是并行性,臭名昭着的全球口译锁(GIL).为此,PyPy表示它可以提供无GIL的Python.

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

Vee*_*rac 642

  1. 正如其他人一直提到的那样,PyPy 对C扩展的支持很少.它支持,但通常速度比Python速度慢,而且最多也是如此.因此很多模块只需要 CPython.Cython和Numpy 对于数字来说非常棒,大多数真正需要Python速度的人都在大量使用它们(+ Pandas,SciPy等).由于它们要么不存在,要么得到支持而且速度慢,需要快速Python的人通常会因为速度和易用性而更好地使用CPython.
  2. Python 3支持目前是实验性的. 刚刚达到稳定!截至2014年6月20日,PyPy3 2.3.1 - Fulcrum已经淘汰!
  3. PyPy有时并不真正更快"脚本",其中有很多人使用Python进行.这些是短期运行的程序,可以做一些简单而小巧的事情.因为PyPy是一个JIT编译器,它的主要优点来自长运行时间和简单类型(例如数字).坦率地说,与CPython相比,PyPy的JIT前速度非常差.
  4. 惯性.迁移到PyPy通常需要重组,这对某些人和组织来说太过分了.

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

注意:这个问题很古老!避免从过时的信息中得出结论.

  • @Veedrac这就是我的意思.就像在"看看cblas和lapacke中的函数签名"一样,因为它们太长而且难以使用,你会立即理解为什么我们使用Python来绕过指针和元数据. (25认同)
  • PyPy"与C一样快"更多地是关于通用C而不是用于数值的高度优化的多线程缓存感知C库.对于数字,Python只是习惯于指向大数组的指针.所以PyPy"和C一样快"意味着"你的指针+元数据会像C一样快速移动".没有大碍.那么为什么要烦扰Python呢?去看看cblas和lapacke中的函数签名. (18认同)
  • 很高兴您提到重组.例如,我的Web主机可以在Python 2.4和2.5之间进行选择; 我附近的"主要娱乐软件生产商"使用的是2.6,没有计划很快升级.有时甚至发现转换成本可能是一项重大而昂贵的工作. (14认同)
  • @ cjordan1:我不明白你在说什么.高级numpy结构非常富有表现力(`np.sum(M [1:2*n**2:2,:2*n**2]*M [:2*n**2:2,:2*n**2] .conjugate(),axis = 1)`?)在Python中,它使Python非常适合科学界.此外,在Python中执行非密集部分并为较小的密集循环执行C外壳是一种常见且可用的策略. (12认同)
  • @ tommy.carstensen这不是一个真正深入的好地方,但我会尝试.**1.**当我写这篇文章时,这比现在更加真实.**2.**"脚本"非常重要.PyPy的IO仍然比CPython慢​​ - 它过去常常慢得多.**3.**PyPy在处理字符串时曾经比CPython慢​​ - 现在它通常更好而且很少更糟.**4.**许多"脚本"只是粘合代码 - 在这种情况下,使解释器更快不会改善整体运行时间.**5.**PyPy的预热时间过去比较大 - 短时间运行的脚本很少能够产生大量热门代码. (5认同)
  • 我记得几个星期前读过这个页面,而且消息是PyPy不值得.但后来尝试了一个脚本,我通常不得不一夜之间离开,并发现**PyPy产生巨大的差异**.所以我想分享这个发现并鼓励其他人试一试.*PyPy实际上并不比"脚本"更快*具有误导性...... (4认同)
  • @ostrokach在得到关注之后,我很犹豫是否会明显改变答案(99.8%的选票是肯定的,因此人们对它的态度非常强烈),但我只是稍微更新了一些措辞. (2认同)

spo*_*key 102

该网站并未声称PyPy比CPython快6.3倍.报价:

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

这是对你所做的一揽子陈述的一个非常不同的陈述,当你理解这些差异时,你至少会理解为什么你不能只说"使用PyPy"的一组理由.这可能听起来像是挑剔,但理解为什么这两个陈述完全不同是至关重要的.

打破这种情况:

  • 他们所作的陈述仅适用于他们使用的基准.它绝对没有说明你的程序(除非你的程序与他们的一个基准测试完全相同).

  • 该声明大约是一组基准的平均值.没有人声称即使对于他们测试的程序,运行PyPy也会提高6.3倍.

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

  • 当然没有人声称PyPy会更快地运行所有Python代码.但是如果你采用所有纯Python应用程序,我可以打赌,其中绝大多数将在PyPy上运行得更快(> 3倍)然后在CPython上运行. (15认同)
  • 你的前两个要点都没有意义.怎么能说基准测试"绝对没有关于你的程序".很明显,基准测试不是所有实际应用程序的完美指标,但它们绝对可以作为指标.另外,我不明白你发现什么误导他们报告一组基准的平均值.他们很清楚地表明这是一个平均值.如果程序员不理解平均值是什么,那么他们就会比语言表现更严重. (14认同)
  • @SeanGeoffreyPietz - 我没有声称PyPy的网站有任何误导性 - 他们已经准确地展示了他们的结果.但最初的问题错误引用了他们,并且证明了作者并不理解"平均"这个词的重要性.许多单独的基准测试速度并不快6.3倍.如果使用不同类型的平均值,则得到不同的值,因此"6.3 x更快"并不是"几何平均值快6.3 x"的充分摘要."A组比B组快Z倍"太模糊,没有意义. (6认同)
  • -1:@spookylukey你似乎暗示基准套件存在偏见而没有提供支持索赔的证据.批评应该始终有证据支持! (5认同)
  • @EvgeniSergeev - 不,我暗示所有基准都有偏见!当然不一定是故意的.可能有用的程序空间是无限的,并且变化多端,一组基准测试只测量这些基准测试的性能.问"PyPy比CPython快多少?" 就像问"如果弗雷德比乔快多少?",这就是OP似乎想知道的. (5认同)

Tri*_*m21 69

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

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

  • @knite 1:这是2015年的新版本,该文档历史上已读取8 GB.2:在2015年的练习中,你仍然需要至少8,免费6-7. (4认同)
  • 如果使用[build或distribution](http://pypy.org/download.html),编译的内存要求就不那么重要了.至于"移动目标,高度实验性",你能举几个例子吗?同样,如果人们使用发布版本而不是夜间版本或源代码,那么他们是否对功能有合理的期望? (3认同)
  • 根据http://pypy.org/download.html的介绍,PyPy需要4 GB的RAM进行编译(在64位系统上),而不是8。如果需要,该页面上有一个选项可以在3 GB以下进行编译。 (2认同)
  • @Tritium21:我只对当前的答案感兴趣。它是什么?您可能想编辑您的答案,说*“截至 2013 年,比较 pypy 与 Python 2.x 版本是......”* 另外,如果问题中的“6.3x 几何平均”声明已过时([截至 2017 年 4 月,他们声称是 7.5 倍,但即便如此,也取决于基准测试...](http://speed.pypy.org)),那么也需要编辑(版本号、最新数据等) )我认为基准测试套件不是很相关,现在几乎没有人会在 CPU 上用脚本语言运行光线跟踪。我确实找到了 https://pybenchmarks.org (2认同)

Bre*_*arn 35

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

至于第一个问题,我认为它是第一个问题的第二个问题:PyPy一直在快速发展,以提高速度并增强与其他代码的互操作性.这使它比官方更具实验性.

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

  • 我不认为C语言很快就会出现在任何地方(我愿意说,它不会在我们的一生中消失).直到有另一种语言可以在任何地方运行,我们将有C.(注意,JVM是用C编写的.即使是java,"无处不在"的语言也需要C来实现它的无处不在.)否则我同意这篇文章的大部分内容.它的观点. (16认同)
  • @BrenBarn声称Python对C的依赖是有害的,这完全是愚蠢的.如果没有Python的C-API,Python在其成长的青少年时期(90年代末期)获得的大多数非常强大的库和强大的互操作,包括整个数字/科学生态系统和GUI界面,都是不可能的.在制作这样的一揽子陈述之前,请四处寻找Python的整个使用范围. (10认同)
  • @Tritium21:是的,我只是在那里进行编辑.我很喜欢C存在,但我认为Python对C的依赖是非常有害的,PyPy就是一个很好的例子:现在我们有机会获得更快的Python,但是我们被多年依赖C绊倒了Python站在自己的双脚上要好得多.如果Python本身是用C语言编写的,那就更好了,但问题是存在一种扩展机制,鼓励人们以依赖于C的方式扩展Python. (7认同)
  • 双刃剑 - 使python如此受欢迎的部分原因是它能够扩展其他应用程序并被其他应用程序扩展.如果你拿走它,我认为我们不会谈论python. (4认同)
  • @PeterWang所有这些库都可以用Python编写,但它们不会像它们那样快.BrenBarn所说的是现在我们有机会让python足够快,以便这些库可以用python编写,但我们拒绝抓住这个机会,因为采取它意味着失去使用C库的能力.我相信这就是他有意义的意思,而不是C库的存在是一件坏事,但制作快速库的唯一方法就是使用C. (4认同)

Eri*_*ban 14

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

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

  • @AlexRubinsteyn但那些PyPy工作的看法一直一般是,如果你发现一个情况下PyPy比CPython的慢,你可以把它变成一个合理的基准,它具有被添加到该套件的一个很好的机会. (9认同)
  • Julian,值得注意的是,PyPy 人员多年来一直致力于改进该特定基准套件的运行时间。在某种程度上,他们似乎对这组基准进行了“过度拟合”,并且根据我的经验,除了纯粹的数值计算(无论如何在 Fortran 或 C99 中效果更好)之外,我从来没有让 PyPy 比这更出色。比 CPython 快大约 2 倍。 (2认同)
  • @gsnedders 我在 [multiple](https://mail.python.org/pipermail/pypy-dev/2015-August) 上提供了基于 [rinohtype](http://www.mos6581.org/rinohtype/) 的基准/013769.html) [场合](https://bitbucket.org/pypy/pypy/issues/2365/rinohtype-much-slower-on-pypy3#comment-34810420)。他们尚未将其添加到套件中。 (2认同)

小智 12

问:与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垃圾收集器的增量特性.


pts*_*pts 7

CPython有引用计数和垃圾收集,PyPy只有垃圾收集.

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

其他一些软件可以同时使用这两种软件,但CPython使用的内存较少,因为之前释放的是未使用的对象.(我没有任何测量结果表明这是多么重要以及其他实现细节会影响内存使用.)

  • 应该强调的是,即使在CPython中,依赖于早期或根本不需要调用`__del__`也是错误的.正如你所说,它*通常*有效,有些人认为它是有保证的.如果引用该对象的任何内容都被引用到参考周期中(这很容易 - 您是否知道以某种非人为的方式检查当前异常会创建一个引用周期?)终止无限期地延迟,直到下一个周期GC (可能**永远不会**).如果对象本身是引用循环的一部分,则根本不会调用`__del __*(在Python 3.4之前). (17认同)
  • CPython中每个对象的开销更高,一旦开始创建大量对象,这很重要.我相信PyPy在默认情况下完全相当于__slots__. (3认同)

Ste*_*ont 5

对于很多项目来说,不同的python在速度上实际上有0%的差异。那就是那些以工程时间为主并且所有 python 都具有相同数量库支持的那些。

  • @user 好吧,即使 PyPy 快了一千倍,任何需要一个月才能编写并运行一分钟的运行一次项目,使用 PyPy 的总体速度将提高 0.0%(1 个月 + 1 分钟 vs 1 个月)。Stephan 并没有声称所有项目都会有 0% 的加速。 (3认同)
  • 和简单一点关系都没有。在工程时间中,反馈循环很重要。有时比运行时间更重要。 (2认同)

Yis*_*hen 5

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

  • “含电池”是指*大型标准库*,AFAIK (19认同)

lif*_*ofi 5

我找到了一些例子,其中 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
Run Code Online (Sandbox Code Playgroud)

因此,如果您想到 PyPy,请忘记 Windows。在 Linux 上,您可以实现惊人的加速。示例(列出 1 到 1,000,000 之间的所有素数):

from sympy import sieve
primes = list(sieve.primerange(1, 10**6))
Run Code Online (Sandbox Code Playgroud)

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