我听说了很多关于Pypy项目的事。他们声称这比他们网站上的cpython解释器快6.3倍。
每当我们谈论像Python这样的动态语言时,速度是首要问题之一。为了解决这个问题,他们说Pypy的速度是6.3倍。
第二个问题是并行性,臭名昭著的全局解释器锁(gil)。为了这个,派比说它可以给吉尔更少的Python。
如果Pypy能够解决这些巨大的挑战,那么它的哪些弱点阻碍了更广泛的采用呢?也就是说,是什么阻止了像我这样的典型的Python开发人员现在切换到pypy?
- 清除评论,因为大多数东西要么在答案中充实(在某些情况下是),要么根本不应该说。还编辑了一些关于这个问题主观性的问题。请尝试用事实回答,如果可能,请用来源备份断言!
- 我经常用派比。它往往工作得很好。然而,虽然Pypy对于许多CPU负载比较重的工作负载来说速度要快一些,但对于我抛出的I/O负载来说,实际上速度要慢一些。例如,我编写了一个消除重复数据的备份程序backshift。对于执行大量文件分块的初始备份,pypy非常好。但是对于后续的备份(主要是更新时间戳),cpython更快。
正如其他人很快提到的,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.
- 很高兴你提到再加工。例如,我的网络主机在python 2.4和2.5之间有一个选择;而我附近的一个"娱乐软件的主要生产商"正在使用2.6,而且不打算很快升级。有时甚至发现转换的成本可能是一项重大而昂贵的工作。
- Pypy"和C一样快"更多的是关于通用C,而不是用于数字的高度优化的多线程缓存感知C库。对于数字,python只是用来传递指向大数组的指针。所以pypy"和c一样快"意味着"你的指针+元数据移动的速度和c一样快"。没什么大不了的。那为什么还要管Python呢?去看看cblas和lapacke中的函数签名。
- @米凯豪斯基:太可怕了。这两个版本都非常古老。2.7是最新的python2版本,作为开发人员,您真的希望2.6+不会很快发疯。
- @乔丹:我不明白你说的话。高级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是一种常见且可用的策略。
- @这就是我的意思。就像在"查看cblas和lapacke中的函数签名"中一样,因为它们太长而且很难使用,所以您会立即理解为什么我们使用python来传递指针和元数据。
- @Veedrac这些构造非常强大,但是将它们转换为C实现调用可能不会花费那么多时间。我相信cjordan1所说的"只是用来传递指针"是指没有在python中做过实质性的工作,这是正确的。(也许用"大部分"而不是"只是"会更好。)
- @millimoose我不确定你所说的"实质性"是什么意思,但是很多麻木/熊猫/等等都是在Python身上,只是不是那些需要快速的东西。哎呀,熊猫甚至在赛通。
- Pypy不假定/设计为在非抖动模式下运行。类似的,你将运行JAVA支持JIT的JVM。
- @罗伯特扎伦巴,我说的是代码的非抖动部分,又名。当代码路径没有预热时,相对于cpython来说速度相当慢(部分原因是JIT的开销,尽管javascript可以做到这一点)。
- "第三,Pypy的"脚本"速度并不是更快吗?"这不是真的。你从哪里得到这种误解的?
- @汤米。卡斯滕森,这不是一个深入的好地方,但我会努力的。1。这在我写的时候比现在更真实。2。脚本"通常很重。Pypy的IO通常还是比CPython的慢-它以前慢得多。三。Pypy过去在处理字符串时比CPython慢——现在它通常更好,很少更糟。4。许多"脚本"只是粘合代码——在这种情况下,使解释器更快并不能提高总体运行时间。5。Pypy的预热时间过去是一个大的、短时间运行的脚本,很少能产生很多热代码。
- @Veedrac我有一个处理20GB XML数据的脚本,其中pypy比python快15倍。
- @奥斯特洛克,你是在评论我提出的一个特别的要求吗?请注意,自2013年底以来,情况发生了很大变化。
- 我记得几周前读过这篇文章,我的意思是Pypy不值得。但后来在一个剧本上尝试了一下,我通常要在一夜之间离开,结果发现Pypy有很大的不同。所以我想分享这个发现并鼓励其他人尝试一下。Pypy实际上不是更快的"脚本"是误导…
- @Ostrokach我在得到关注后犹豫是否要改变一个答案(99.8%的选票是正面的,所以人们对它的赞同程度相当强烈,就像措辞一样),但我只是稍微更新了一下这里的措辞。
该网站没有声称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会更快地运行所有python代码。但是,如果您使用所有纯Python应用程序,我敢打赌,它们中的大部分将在pypy上运行得更快(超过3倍),然后在cpython上运行。
- 前两个要点都没有意义。你怎么能说基准测试"对你的程序毫无意义"。很明显,基准不是所有实际应用程序的完美指示器,但它们绝对可以作为指示器使用。另外,我不明白你发现他们报告一组基准的平均值有什么误导性。他们说的很清楚,这是一个平均值。如果程序员不理解平均值是多少,那么他们比语言性能更关心问题。
- 另外,你所说的"网站不声称Pypy比CPython快6.3倍"似乎是纯语义的。当他这么说的时候,有一个相当明确的暗示(至少对我来说)他说的是一个平均值。如果基准速度不是6.3倍,那么它们的速度有多快?
- @Seangeoffreypietz——我并没有说Pypy的网站有任何误导性——他们准确地展示了他们的结果。但最初的问题错误地引用了他们的话,表明作者不理解"平均"这个词的重要性。许多个别基准的速度都不是6.3倍。如果使用不同类型的平均值,则会得到不同的值,因此"6.3 x更快"不是"几何平均值是6.3 x更快"的充分总结。A组比B组快Z倍"太模糊了,没有意义。
- -1:@spokylukey您似乎建议基准套件存在偏见,而不提供支持声明的证据。批评应该总是有证据支持的!
- @不,我暗示所有的基准都是有偏见的!当然,不一定是故意的。可能有用的程序的空间是无限的,而且变化非常大,而且一组基准只测量这些基准的性能。问"Pypy比CPython快多少?"就像问"如果弗雷德比乔快多少?"这就是OP想要知道的。
- 这里有一个比cpython 3慢的例子:这个代码在pypypy上花费了218毫秒,而在python3上花费了124毫秒:codeforces.com/contest/278/submission/9820817,这是一个罕见的例子,大多数其他代码在pypy pypy上花费的时间比python少。
- 基准点显示了各主要部分的进展和速度。然而,在同一个网站上,他们承认Pypy的速度比Cpython慢4例,即:Cpython C扩展模块、缺少Rpython模块、ITertools和Ctypes的滥用。这些案例是他们未来工作的重点。
因为pypy不是100%兼容的,需要8 Gigs的RAM来编译,是一个移动的目标,而且是高度实验性的,其中cpython是稳定的,是20年来模块构建者的默认目标(包括不在pypypy上工作的C扩展),并且已经广泛部署。
Pypy可能永远不会是引用实现,但它是一个很好的工具。
- 根据pypy.org/download.html,pypy需要4 GB的RAM来编译(在64位系统上),而不是8。如果需要的话,在该页面上有一个选项可以在3GB以下完成。
- @Knite1:这是截至2015年的最新版本,文档的历史读数为8GB。2:在2015年的实践中,至少需要8个,6-7个是免费的。
- 如果使用构建或分发,那么编译所需的内存就不那么重要了。至于"移动的目标,高度实验性的",你能举几个例子来说明那些破碎的东西吗?同样,如果人们使用的是发布版本而不是夜间版本或源代码,那么他们对功能的期望是否合理?
- @这是一个基于古代数据的古老问题,有着古老的答案。考虑到这个问题和每一个答案对于4年前的Pypy来说都是历史性的。
- @我只对目前的答案感兴趣。它是什么?您可以编辑您的回答,说"截至2013年,对比pypy与python 2.x版本是……",如果问题中的"6.3x几何平均值"声明已过期(截至2017年4月,它们声称7.5x,但即便如此,还取决于基准……),那么也需要编辑(版本号、最新数据等),我认为基准套件是不太相关,现在几乎没有人会在CPU上用脚本语言运行光线跟踪。我确实找到了pybenchecks.org
- @中芯国际欲获得最新答案,请再次提出问题,并尝试将此问题作为其副本关闭。这个问题本身已经过时了。
第二个问题更容易回答:如果您的所有代码都是纯Python,那么您基本上可以使用pypy作为替换。然而,许多广泛使用的库(包括一些标准库)是用C语言编写的,并编译为Python扩展。其中一些可以用来和pypy一起工作,有些不能。pypy提供了与python相同的"前向"工具,也就是说,它是python,但是它的内部是不同的,因此与这些内部接口的工具无法工作。
至于第一个问题,我认为它有点像第一个问题的第22条:Pypy一直在快速发展,以提高速度和增强与其他代码的互操作性。这使得它比官方更具实验性。
我认为,如果Pypy进入稳定状态,它可能会开始得到更广泛的应用。我还认为,对于Python来说,从它的C基础上转移出去是非常好的。但暂时不会发生。Pypy还没有达到临界质量,它本身几乎足够有用,可以做任何你想做的事情,这将激励人们填补空白。
- 我不认为C语言很快就会出现在任何地方(我愿意说,它不会在我们的一生中消失)。除非有另一种语言在任何地方运行,否则我们将有C(注意,JVM是用C语言编写的,甚至Java),"到处运行的语言"都需要C来代替它。
- @特里图姆21:是的,我只是在那里发表社论。我对C的存在很满意,但我认为python对C的依赖是非常有害的,pypy就是一个很好的例子:现在我们有机会获得更快的python,但是我们被多年依赖C的经历绊倒了。对python来说,依靠自己的双脚站立会更好。如果Python本身是用C语言编写的,这甚至是可以的,但问题是存在一个扩展机制,它鼓励人们以依赖C的方式扩展Python。
- 双刃剑——让Python如此受欢迎的部分原因是它能够扩展其他应用程序并被其他应用程序扩展。如果你把它拿走,我想我们不会谈论Python。
- 如果您取消了C支持,我们将不会有很多C绑定到只存在于较低级别的库,因为这样做很容易。像xlib这样的东西很有用,而放弃对它的支持来帮助jit的口译员有点倒退。我说,让需求本身说明问题。如果Pypy的jit速度和现代资金过剩的javascript解释器一样快,可能会有所不同。
- @布伦巴恩断言Python对C的依赖是有害的,这完全是愚蠢的。如果没有python的C-api,那么python在十几岁(90年代末)形成的时期(包括整个数字/科学生态系统和GUI界面)所获得的大多数真正强大的库和出色的互操作性将不可能实现。在做出这些笼统的声明之前,请四处看看,了解一下Python的整个使用领域。
- @peterwang所有这些库都可以用python编写,但是它们的速度不会像现在这样快。Brenbarn所说的是,现在我们有机会让python足够快,以便那些libs可以用python编写,但我们拒绝接受这个机会,因为接受它意味着失去使用c库的能力。我相信这就是他所说的有害的意思,不是说C库的存在是一件坏事,而是说让库快速运行的唯一方法就是使用C。
- 是的,基本上是维基说的。对于Python来说,C接口是可能的,这非常好。对python不利的是,C接口对于很多事情来说都是必要的,而对python不利的是,由于对基于C的模块的累积依赖,C接口现在变得更加必要了。
- 为支持C扩展的Python编写JIT编译器有多困难?
- @JIT无法解释C部分,因此可能无法安全地优化掉大量调用。这可能会使它比cpython慢。哦,而且它必须公开与cpython相同的API,这可能会阻塞很多东西。
- @我对编译器不是很了解,所以如果这是一个愚蠢的问题,请原谅我,但是如果Pypy不能,Luajit为什么能够实现一个与C API一起工作的跟踪jit编译器呢?
- @Seangeoffreypietz我只是说说为什么它不能像他们想要的那样表现,他们真的很喜欢表现。看起来Pypy确实有类似于Lua的C接口,因为c ffi来自Lua的ffi。cffi.阅读docs.org/en/release-0.8
- @Seangeoffreypietz您的问题可能应该作为一个问题发布,但从我所看到的情况来看,问题是Luajit的C API用于Lua与C代码交互,而CPython的C模块用于C处理python运行时。Lua也有类似于Cpython C模块的东西,Luajit的C与C模块的视角不同(我认为)。
- 更多信息:pypy.readthedocs.org/en/latest/…
- 那努巴呢?
我在这个问题上做了一个小基准。虽然许多其他的海报在兼容性方面都做得很好,但我的经验是,Pypy并没有那么快,只需移动位。对于python的许多用途,它实际上只存在于两个或多个服务之间转换位的情况。例如,没有多少Web应用程序正在对数据集执行CPU密集型分析。相反,它们从客户机获取一些字节,将它们存储在某种数据库中,然后将它们返回到其他客户机。有时数据的格式会改变。
bdfl和cpython开发人员是一个非常聪明的群体,他们帮助cpython在这种情况下表现出色。下面是一个不知羞耻的博客插件:http://www.hydrogen18.com/blog/unpickling-buffers.html。我使用的是Stackless,它是从CPython派生的,并保留了完整的C模块接口。在这种情况下,我没有发现使用pypy有什么好处。
- Pypy有许多仔细运行的基准(不幸的是,与CPython不同,后者目前还没有真正面向用户的基准套件)。当然,对于网络流量,Pypy不能神奇地使任何东西更快。
- 朱利安,值得注意的是,多年来,Pypy的人一直在努力改进这个特定基准套件的运行时间。在某种程度上,他们似乎"过度"地将他们的优化应用于这组基准,根据我的经验,除了纯数值计算(在Fortran或C99中效果更好),我从来没有让Pypy比Cpyton快大约2倍。
- @Alexrubinsteyn但是那些研究pypy的人的观点通常是,如果你发现pypy比cpython慢,你可以把它变成一个合理的基准,它有很好的机会被添加到套件中。
- 我看了你的博客。在您的结果中,普通的python对(pickle,stringio)显示pypy比cpython快6.8倍。我认为这是一个有用的结果。在您的结论中,您正确地指出了pypy代码(纯Python!)比C代码(cpickle、cstringio)慢,而不是cpython代码。
- @我多次提供了一个基于RinohType的基准。他们还没有将其添加到套房中。
问:与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使用较少的内存,因为未使用的对象会更早地被释放。(我没有任何度量来指示这有多重要,以及其他实现细节对内存使用的影响。)
- 应该强调的是,依赖于早期或根本上被称为__del__,即使在cpython也是错误的。正如你所说,它通常是有效的,有些人认为这意味着它是有保证的。如果引用对象的任何内容被卷入引用循环(这很容易——您知道以某种非人为方式检查当前异常会创建引用循环吗?)终结无限期地延迟,直到下一个周期gc(可能永远不会)。如果对象本身是引用循环的一部分,则根本不会调用__del__(在Python3.4之前)。
- 在cpython中,每个对象的开销更高,一旦开始创建许多对象,这就非常重要。我相信Pypy在默认情况下做的相当于slots,一方面。
我发现了一些例子,其中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都有相同数量的图书馆支持。
- 如果您的项目如此简单,那么显然它并不重要,但是任何语言的实现都可以这样说:如果您所做的只是通过相对性能的abis聚合其他库的函数,那么这一切都无关紧要。
- 它与简单没有任何关系。在工程中,反馈回路很重要。有时比运行时间更重要。
- 好吧,你说得很含糊(工程时间不涉及正在设计的东西,约束是什么,等等;反馈循环不涉及反馈给谁的东西,等等),所以我要退出这段对话,而不是交换神秘的引用。
- 这里没有什么含糊的。看看ooda循环,或者pda。
- "很多项目"是模糊的,"差异"是模糊的,"速度"是模糊的,"图书馆支持"是模糊的。OODA和PDCA?我认为你只是在控制——无论你谈论的是什么实现(假设你真的在谈论Python代码),这两个方面都很模糊,而且它们是"很多项目"中的两个例子,即使你谈论的是具体的实现。
- Stephan。我个人的经验是,Pypy速度更快,记忆力更差。我的用例有点不寻常(大数据),但是你所说的额外的"工程时间"对我来说是不存在的。选择并不比通过cpython运行或(琐碎的)安装pypy并通过它运行更复杂。后者是一个巨大的胜利。如果你试图反驳这一经验,一些可靠的事实会对你的案件有所帮助。举证责任在你身上,因为你声称有"0%的差异"。
- 你在做大数据,这就是执行速度和内存使用的关键所在。
- 那太白痴了。从大数据到嵌入式,从商业到游戏,在很多地方速度和内存使用都很重要。
- 发帖前先想一想。
- @用户好吧,任何一个只运行一次的项目都需要一个月的时间和一分钟的运行时间,从使用pypy到使用pypy的总速度将提高0.0%(1个月+1分钟对1个月),即使pypy快了1000倍。斯蒂芬并不是说所有的项目都会加速0%。
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月)是试用版。