ChatGPT解决这个技术问题 Extra ChatGPT

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

我听说过很多关于 PyPy 项目的信息。他们声称它比 their site 上的 CPython 解释器快 6.3 倍。

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

第二个问题是并行性,即臭名昭著的 Global Interpreter Lock (GIL)。为此,PyPy 说它 can give GIL-less Python

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

清除评论,因为大多数内容应该在答案中充实(在某些情况下是),或者根本不应该说。还进行了编辑以解决对该问题的主观性提出的一些担忧。请尝试使用事实来回答,并尽可能用来源支持断言!
我一直在使用 Pypy。它往往工作得很好。然而,虽然 Pypy 对于许多 CPU 密集型工作负载来说要快得多,但对于我所投入的 I/O 密集型工作负载来说它实际上要慢一些。例如,我编写了一个名为 backshift 的重复数据删除备份程序。对于执行大量文件分块的初始备份,pypy 非常棒。但是对于大部分只是更新时间戳的后续备份,CPython 更快。

V
Veedrac

注意:PyPy 现在比 2013 年被问到这个问题时更成熟,得到更好的支持。避免从过时的信息中得出结论。

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

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


很高兴你提到重组。例如,我的虚拟主机可以在 Python 2.4 和 2.5 之间进行选择;我附近的“娱乐软件主要生产商”正在使用 2.6,并且没有计划很快升级。有时,甚至发现转换成本可能是一项重大而昂贵的工作。
PyPy “与 C 一样快”更多的是关于通用 C,而不是用于数字的高度优化的多线程缓存感知 C 库。对于数字,Python 仅用于传递指向大数组的指针。因此,PyPy “与 C 一样快”意味着“您的指针+元数据的移动速度与 C 一样快”。没有大碍。那为什么还要用 Python 呢?去看看 cblas 和 lapacke 中的函数签名。
@cjordan1:我不明白你在说什么。高级 numpy 构造在 Python 中极具表现力(np.sum(M[1:2*n**2:2, :2*n**2] * M[:2*n**2:2, :2*n**2].conjugate(), axis=1)?),这使得 Python 非常适合科学界。此外,在 Python 中完成非密集部分并为较小的密集循环使用 C 语言是一种常见且可用的策略。
@Veedrac 这就是我的意思。就像“去看看 cblas 和 lapacke 中的函数签名”一样,因为它们太长且难以使用,以至于您会立即理解为什么我们使用 Python 来传递指针和元数据。
@tommy.carstensen 这不是一个深入研究的好地方,但我会尝试。 1. 这在我写它的时候比现在更真实。 2.“脚本”通常是 IO 繁重的。 PyPy 的 IO 仍然通常比 CPython 慢 - 它曾经明显慢得多。 3. PyPy 过去在处理字符串方面比 CPython 慢——现在它通常更好,很少更差。 4. 许多“脚本”只是胶水代码——在这种情况下,让解释器更快不会提高整体运行时间。 5. PyPy 的预热时间过去更长——运行时间短的脚本很少能产生大量热代码。
s
spookylukey

该网站并未声称 PyPy 比 CPython 快 6.3 倍。去引用:

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

这是与您所做的一揽子声明非常不同的声明,当您了解其中的区别时,您将理解至少一组不能只说“使用 PyPy”的原因。听起来我在吹毛求疵,但理解为什么这两个陈述完全不同是至关重要的。

打破它:

他们所做的声明仅适用于他们使用的基准。它完全没有说明您的程序(除非您的程序与他们的基准测试之一完全相同)。

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

没有人声称 PyPy 甚至可以运行 CPython 运行的所有程序,更不用说更快了。


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

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

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


根据 pypy.org/download.html,PyPy 需要 4 GB 的 RAM 来编译(在 64 位系统上),而不是 8。如果需要,该页面上有一个选项可以在 3 GB 以下进行。
@knite 1:这是 2015 年的新内容,文档历来读取 8 GB。 2:2015年实践中你至少还需要8个,有6-7个免费。
如果您使用 build or distribution,则编译的内存要求并不那么重要。至于“移动目标,高度实验性”,你能举几个破坏的例子吗?同样,如果人们使用的是发布版本而不是夜间版本或源代码,他们对功能没有合理的期望吗?
@smci 这是一个基于古代数据的古老问题,有古老的答案。考虑这个问题和每个答案对于 pypy 4 年前的状态都是历史性的。
@Tritium21:我只对当前答案感兴趣。它是什么?您可能想编辑您的答案,说 “截至 2013 年,比较 pypy 与 Python 的 2.x 版本是......” 此外,如果问题中的“6.3x 几何平均”声明是过时(as of 4/2017 they claim 7.5x, but even then depends on the benchmarks...),那么也需要编辑(版本号、最新数据等) .我确实找到了 pybenchmarks.org
B
BrenBarn

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

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

我认为如果 PyPy 进入稳定状态,它可能会开始得到更广泛的使用。我也认为 Python 摆脱它的 C 基础会很棒。但暂时不会发生。 PyPy 还没有达到临界质量,它几乎可以自己做任何你想做的事情,这将激励人们填补空白。


我不认为 C 是一种很快就会出现在任何地方的语言(我愿意说,它不会在我们的有生之年消失)。除非有另一种可以在任何地方运行的语言,否则我们将拥有 C。(注意,JVM 是用 C 编写的。即使是 java,这种“无处不在”的语言也需要 C 来实现它的无处不在。)否则我同意这篇文章的大部分内容其点。
@Tritium21:是的,我只是在那里发表社论。我对现有的 C 很好,但我认为 Python 对 C 的依赖是非常有害的,而 PyPy 就是一个很好的例子:现在我们有机会获得更快的 Python,但我们被多年依赖 C 绊倒了. Python 自己两只脚站立会好很多。如果 Python 本身是用 C 编写的,那也没关系,但问题是存在一种扩展机制,它鼓励人们以依赖 C 的方式扩展 Python。
这方面的双刃剑——让 python 如此受欢迎的部分原因是它能够扩展其他应用程序并被其他应用程序扩展。如果你把它拿走,我认为我们不会谈论 python。
@BrenBarn 声称 Python 对 C 的依赖是有害的,这完全是愚蠢的。如果没有 Python 的 C-API,Python 在其青少年时期(90 年代后期)获得的大多数真正强大的库和出色的互操作性,包括整个数字/科学生态系统和 GUI 界面,都是不可能的。在做出这样的笼统陈述之前,环顾四周以了解 Python 的整个用法。
@PeterWang所有这些库都可以用Python编写,但是它们不会像现在那么快。 BrenBarn 的意思是,现在我们有机会让 python 足够快,以便可以用 python 编写这些库,但我们拒绝抓住这个机会,因为抓住它意味着失去使用 C 库的能力。我相信这就是他所说的有害的意思,并不是说 C 库的存在是一件坏事,而是制作快速库的唯一方法是使用 C。
E
Eric Urban

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

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


PyPy 有许多仔细运行的 benchmarks(不幸的是,与 CPython 不同,它目前还没有真正的面向用户的基准测试套件)。当然,对于网络流量,PyPy 不能神奇地让任何事情变得更快。
Julian,值得注意的是,PyPy 人员多年来一直致力于改进特定基准套件的运行时。在某种程度上,他们似乎对这组基准“过度拟合”了他们的优化,并且根据我的经验,除了纯数值计算(无论如何在 Fortran 或 C99 中更好),我从来没有让 PyPy 变得更多比 CPython 快约 2 倍。
@AlexRubinsteyn 但是那些在 PyPy 上工作的人的观点通常是,如果你发现 PyPy 比 CPython 慢的情况,并且你可以将它变成一个合理的基准,它很有可能被添加到套件中。
我检查了你的博客。在您的结果中,纯 python 对 (pickle, StringIO) 表明 pypy 比 cpython 快约 6.8 倍。我认为这是一个有用的结果。在您的结论中,您(正确地)指出 pypy 代码(它是纯 python!)比 C 代码(cPickle、cStringIO)慢,而不是 cpython 代码。
@gsnedders 我在 multiple occasions 上提供了基于 rinohtype 的基准。他们还没有将它添加到套件中。
佚名

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

A:首先,几乎没有证据表明 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 不是 100% 与 CPython 兼容,因为它没有在底层模拟 CPython。一些程序可能仍然依赖于 CPython 的独特特性,而 PyPy 中没有这些特性,例如 C 绑定、Python 对象和方法的 C 实现,或者 CPython 垃圾收集器的增量特性。


这个答案没有引用任何基准或提供参考。
p
pts

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

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

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


应该强调的是,即使在 CPython 中,依赖 __del__ 被提前调用或根本不正确也是错误的。正如您所说,它通常有效,有些人认为这意味着它是有保证的。如果引用该对象的任何内容都陷入了引用循环中(这很容易 - 你知道以某种非人为的方式检查当前异常会创建一个引用循环吗?)最终确定会无限期延迟,直到下一个循环 GC (可能从不)。如果对象本身是引用循环的一部分,则不会调用 __del__(在 Python 3.4 之前)。
CPython 中每个对象的开销更高,一旦您开始创建大量对象,这很重要。我相信 PyPy 默认情况下相当于插槽,一方面。
S
Stephan Eggermont

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


如果您的项目如此简单,那么显然没关系,但任何语言的任何实现都可以这样说:如果您所做的只是通过相对高性能的 ABI 聚合其他库的功能,那么这一切都无关紧要。
它与简单无关。在工程时间里,反馈回路很重要。有时比运行时间更重要。
好吧,您说得非常含糊(工程时间不涉及正在设计的内容,约束是什么等;反馈循环不涉及反馈给谁的内容等),所以我要走了退出这次谈话,而不是交换神秘的参考资料。
这里没有什么含糊的。看看 OODA 循环或 PDCA。
@user 好吧,任何需要一个月编写和一分钟运行一次的项目,使用 PyPy 的总体速度将提高 0.0%(1 个月 + 1 分钟对 1 个月),即使 PyPy 快一千倍。 Stephan 并没有声称所有项目都会有 0% 的加速。
Y
Yishen Chen

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


“含电池”是指大型标准库,AFAIK
l
lifolofi

我找到了一些例子,其中 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 sieve
primes = list(sieve.primerange(1, 10**6))

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


有趣的!更多的比较和数字会很棒。
q
qwr

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

对于许多科学计算,尤其是矩阵计算,numpy 是更好的选择(参见FAQ: Should I install numpy or numpypy?)。

Pypy does not support gmpy2. 您可以改用 gmpy_cffi,尽管我没有测试它的速度,而且该项目在 2014 年发布了一个版本。

对于 Project Euler 问题,我经常使用 PyPy,对于简单的数值计算,通常 from __future__ import division 足以满足我的目的,但截至 2018 年,Python 3 支持仍在进行中,最好的选择是在 64 位 Linux 上.截至 2018 年 12 月的最新版本 Windows PyPy3.5 v6.0 处于测试阶段。


M
Martin Thoma

支持的 Python 版本

引用 Zen of Python

可读性很重要。

例如,Python 3.8 引入了 fstring =

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

无耻的自我宣传:Killer Features by Python version - 如果您想通过使用较旧的 Python 版本了解更多您错过的东西


但是对于相同的 Python 版本,PyPyCPython 快 - 我可以理解使用 python3.7 和 3.8 并获得更多好处,但如果我可以使用 PyPy对于某些项目来说,绕过 GIL 并在面向 CPU 的进程中具有更快的并行处理
截至今天 9/OCT/21,PyPy 支持或兼容 python3.7,现在团队正在努力支持 python3.8。参考pypy.org/posts/2021/04/…
@GhassanMaslamani 谢谢!我已经更新了:-)
@aspiring PyPy 有一个 GIL。