加速Python

加速Python,python,optimization,performance,Python,Optimization,Performance,这确实是两个问题,但它们非常相似,为了简单起见,我想我把它们放在一起: 首先:给定一个已建立的python项目,除了简单的代码优化外,还有哪些合适的方法可以加速它 其次:在用python从头开始编写程序时,有哪些好方法可以大大提高性能 对于第一个问题,假设您得到了一个编写得体的项目,您需要提高性能,但您似乎无法通过重构/优化获得多少收益。在这种情况下,除了用C之类的语言重写它,你会怎么做来加速它呢?首先想到的是:。目前,它只在x86上运行 然后。也就是说,使所有全局引用(以及global.a

这确实是两个问题,但它们非常相似,为了简单起见,我想我把它们放在一起:

  • 首先:给定一个已建立的python项目,除了简单的代码优化外,还有哪些合适的方法可以加速它

  • 其次:在用python从头开始编写程序时,有哪些好方法可以大大提高性能


对于第一个问题,假设您得到了一个编写得体的项目,您需要提高性能,但您似乎无法通过重构/优化获得多少收益。在这种情况下,除了用C之类的语言重写它,你会怎么做来加速它呢?

首先想到的是:。目前,它只在x86上运行

然后。也就是说,使所有全局引用(以及global.attr、global.attr.attr…)成为函数和方法内部的本地名称。这并不总是成功的,但总的来说是可行的。这可以手工完成,但显然很乏味


您说过除了代码优化之外,我不想深入探讨这一点,但请注意人们会犯的典型错误(
,因为我在(10000000)
范围内)。

这不一定会加快任何代码的速度,但如果您想避免代码速度变慢,在用Python编程时,这是一个关键知识。“全局解释器锁”(GIL)有可能在多线程程序的行为不被理解的情况下大幅降低其速度(是的,这是我的一点…我有一台漂亮的4处理器机器,一次不会使用超过1.2个处理器)。有一篇介绍性文章,其中有一些链接可以让您开始使用。

通过Python profiler运行您的应用程序。 找到一个严重的瓶颈。 用C重写这个瓶颈。
重复。

Cython和pyrex可用于使用类似python的语法生成c代码。Psyco对于适当的项目来说也是非常棒的(有时你不会注意到速度提升太多,有时它会达到50倍的速度)。 我仍然认为最好的方法是分析代码(cProfile等),然后将瓶颈编码为python的c函数。

通常的怀疑——分析它,找到最昂贵的代码行,找出它在做什么,修复它。如果您以前没有做过很多分析,那么在看似无害的表达式后面可能隐藏着一些巨大的二次循环或字符串重复

在Python中,我发现导致不明显减速的两个最常见原因是字符串连接和生成器。由于Python的字符串是不可变的,因此执行如下操作:

result = u""
for item in my_list:
    result += unicode (item)
将在每次迭代中复制整个字符串两次。这已经被很好地介绍过了,解决方案是使用
“”。加入

result = "".join (unicode (item) for item in my_list)
发电机是另一个罪魁祸首。它们非常容易使用,并且可以极大地简化某些任务,但是应用不好的生成器要比简单地将项目添加到列表并返回列表慢得多

最后,不要害怕在C中重写位Python作为一种动态高级语言,根本无法与C的速度相匹配。如果有一个函数无法在Python中进行优化,请考虑将其提取到扩展模块。


我最喜欢的技术是维护模块的Python和C版本。Python版本的编写尽可能清晰明了——任何bug都应该易于诊断和修复。针对此模块编写测试。然后编写C版本,并对其进行测试。它的行为在任何情况下都应该与Python实现的行为相同——如果它们不同,那么应该很容易找出错误并纠正问题。

人们已经给出了一些好的建议,但您必须注意,当需要高性能时,Python模型是:punt to c。像psyco这样的努力在未来可能会有所帮助,但python不是一种快速语言,它的设计也不是这样的。很少有语言能够很好地处理动态内容,并且仍然能够生成非常快的代码;至少在可预见的未来(以及一些针对快速编译的设计作品),情况会是这样

因此,如果您真的发现自己处于这种困境,那么最好的办法是隔离系统中那些在(好的)python中速度慢得令人无法接受的部分,并围绕将用C重写这些位的想法进行设计。对不起。好的设计有助于减少痛苦。不过,首先用python对其进行原型化,然后您也可以轻松地对c进行健全性检查


毕竟,这对numpy这样的东西来说已经足够好了。不过,我再怎么强调好的设计对你有多大帮助也不为过。如果你只是反复地戳你的python代码,用C语言替换最慢的代码,你可能会陷入一片混乱。请仔细考虑C位的确切位置,以及如何将其最小化并合理封装。

请注意使用psyco:在某些情况下,它实际上会产生较慢的运行时间。特别是在尝试将psyco与用C编写的代码一起使用时。我记不起我读过的这篇文章了,但是专门提到了
map()
reduce()
函数。幸运的是,您可以告诉psyco不要处理指定的函数和/或模块。

关于“第二点:在用python从头开始编写程序时,有哪些好方法可以大大提高性能?”

记住优化的Jackson规则:

  • 规则1:不要这样做
  • 规则2(仅限专家):现在不要这样做
还有克努斯法则:

  • “过早优化是万恶之源。”
更有用的规则在中

  • 不要边走边优化。首先要把它做好。那就快点。优化错误的程序仍然是错误的

  • 记住80/20规则

  • 始终运行“之前”和“之后”基准。否则,你不会知道