使用PyPy加速Python性能的规则

4

我已经编写了一个 Python 程序,并在 pypy 和 python 中运行了它。 我添加了一些计时打印来测量性能差异。 在某些情况下,速度提高了10倍,而在其他情况下没有变化。 有人能否解释一下在编写程序时是否有规则可以遵循,以利用 pypy 给出的潜在加速? 例如,避免某些语法,优先选择某些数据结构等。

我发现速度提高了12倍至1.5倍之间。

2个回答

5

PyPy在处理与(小)整数/浮点数有关的纯数值密集型代码和包含< strong>热循环的情况下,通常比使用可变大小的动态整数/浮点数对象的C / C ++代码更快,因为它可以直接使用本地类型。但是,由于需要在运行时检查类型并编译代码,因此它仍然比本机编译的C / C ++代码慢。

PyPy不喜欢(大)动态代码。 它使用跟踪即时编译器,可以跟踪哪些代码部分更可能被执行,并在运行时动态编译此路径,如果经常执行,则会产生运行时开销。 当有许多执行路径动态更改时,JIT的开销可能很大,并且在最坏的情况下,PyPy可以选择不编译任何路径。 问题是PyPy回退解释器比CPython的解释器慢(由于能够跟踪和编译代码)。 支持一些动态特性,如帧内省,但速度较慢(因为代码不预计大量使用它们)。

对于短暂运行的脚本,PyPy不快,因为JIT必须在运行时编译代码,而JIT的开销或使用回退解释器(比CPython慢)可以高于对此类脚本使用CPython进行解释。

PyPy使用垃圾收集器(GC),而CPython使用自动引用计数(ARC)。 GC在分配/释放许多对象(特别是小临时对象)方面可能更快,但它们需要跟踪存活的对象以了解哪些对象已死亡,然后释放它们。 这意味着处理大量引用和常规对象分配的代码实际上可能会更慢。 这包括动态的基于图形的数据结构

与CPython相比,C绑定API(C扩展和CTypes,但不包括CFFI)往往较慢(主要因为它首先是为CPython设计的)。 这意味着调用许多包装的C函数的粘合代码实际上会比使用PyPy慢。 最近完成了大量工作,显着提高了此情况下PyPy的性能,但据我所知,PyPy仍然较慢。 一个用例示例是对大型Numpy数组的操作(对于小型数组,嵌入式JITs如Numba肯定更好),以及CSV和pickling软件包。

字符串操作往往较慢,尤其是字符串连接。 一个原因是CPython使用高效算法进行字符串操作,这些算法在C中非常优化并且代码库庞大而复杂。 这对于小的PyPy团队来说是一项重要的工作,他们需要重新实现它并保持额外的JIT和GC的复杂性。 因此,操作可能没有很好地优化。 关于连接,低效性来自JIT无法优化中间副本。 话虽如此,需要避免字符串附加循环。

生成器往往比简单的基本循环要慢,越简单越好。人们不应该期望JIT在运行时执行复杂的昂贵优化,因为JIT的开销不应该与代码的其余部分相比太大(而PyPy无法提前知道代码所需的时间)。
全局变量在CPython中速度较慢,但在PyPy中则不是这样。话虽如此,出于软件工程原因,它们也不应该被使用。
这是一个相当广泛的主题。有许多其他有趣的观点可以考虑来评估给定Python代码的性能。要了解更多信息,请阅读:

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接