25

Python 社区发布了有用的参考资料,展示了如何分析 Python 代码,以及 C 或Cython中 Python 扩展的技术细节。我仍在寻找教程,但是,对于非平凡的 Python 程序,以下内容:

  1. 如何通过转换为 C 扩展来识别将从优化中受益的热点
  2. 同样重要的是,如何识别不会从转换为 C 扩展中受益的热点
  3. 最后,如何从 Python 到 C 进行适当的转换,无论是使用 Python C-API 还是(甚至可能更好)使用 Cython。

一个好的教程将为读者提供一种方法论,说明如何通过一个完整的示例来推理优化问题。我没有成功找到这样的资源。

你知道(或者你写过)这样的教程吗?

为了澄清起见,我对涵盖以下内容的教程不感兴趣:

  • 使用 (c)Profile 分析 Python 代码以测量运行时间
  • 使用工具检查配置文件(我推荐RunSnakeRun
  • 通过选择更合适的算法或 Python 结构进行优化(例如,用于成员资格测试的集合而不是列表);本教程应该假设算法和 Python 代码已经是最优的,并且我们正处于 C 扩展是下一个逻辑步骤的地步
  • 重述有关编写 C 扩展的 Python 文档,该文档已经非常适合作为参考,但不能用作说明何时以及如何从 Python 迁移到 C 的资源。
4

4 回答 4

9

第 1 点和第 2 点只是基本的优化经验法则。如果有您正在寻找的那种教程,我会感到非常惊讶。也许这就是你没有找到的原因。我的短名单:

  • 优化的第一条规则是don't
  • 规则二措施
  • 第三条规则确定了限制因素(如果它是 IO 或数据库绑定,则无论如何都可能无法进行优化)。
  • 第四条规则是思考使用更好的算法和数据结构 ......
  • 考虑到语言的变化在名单上是相当低的......

只需从使用常用的 python 工具分析你的 python 代码开始。找到你的代码需要优化的地方。然后尝试使用python对其进行优化。如果仍然太慢,请尝试了解原因。如果它是 IO 绑定的,那么 C 程序不太可能会更好。如果问题来自算法,那么 C 也不太可能表现得更好。确实,C 可以提供帮助的“好”案例非常少见,运行时不应该离您想要的太远(例如 3 倍加速中的 2 倍)数据结构很简单,并且会从低级表示中受益,您真的,真的需要那个加速。在大多数其他情况下,使用 C 而不是 python 将是一项没有回报的工作。

确实,从 python 调用 C 代码时将性能作为主要目标是非常罕见的。更常见的目标是将 python 与一些现有的 C 代码接口。

正如另一位海报所说,您可能会更好地建议使用 cython。

如果您仍然想为 Python 编写 C 模块,所有必要的都在官方文档中。

于 2010-11-15T22:50:43.347 回答
6

O'Reilly 有一个教程(据我所知,免费提供,我可以阅读整篇文章),说明如何分析真实项目(他们使用 EDI 解析项目作为分析的主题)和识别热点。在 O'Reilly 的文章中没有太多关于编写 C 扩展来解决瓶颈的细节。但是,它确实通过一个重要的示例涵盖了您想要的前两件事。

编写 C 扩展的过程在此处得到了很好的记录。困难的部分是想出方法来复制 Python 代码在 C 中所做的事情,这需要一些在教程中很难教授的东西:独创性、算法知识、硬件和效率,以及相当的 C 技能。

希望这可以帮助。

于 2010-11-15T22:26:57.077 回答
4

对于第 1 点和第 2 点,我将使用 Python 分析器,例如cProfile。请参阅此处以获取快速教程。

如果您已经有一个现有的 python 程序,对于第 3 点,您可能需要考虑使用Cython。当然,与其用 C 重写,不如想出一种算法改进来提高执行速度。

于 2010-11-15T22:29:02.350 回答
2

我将尝试解决您的第 1 点和第 2 点,以及您的前 3 个要点,但不是按顺序。

第三个要点说“假设算法和 python 代码已经是最优的”。当代码处于该状态时,如果获取堆栈样本(如此处所述),从时间的角度来看,样本准确地显示了程序正在做什么,并且如果不更改语言,似乎没有什么可以改进的。但是,由于您知道它是如何花费时间的,因此您知道哪种低级算法(可能包含多个函数,而不仅仅是一个热点)可以通过减少时间来受益,即通过转换为 C .

关于第 1 点,此方法显示代码的哪些部分将受益于转换为 C,它们可能是也可能不是热点。(首先想到的是任何类型的递归函数或函数集。或者,一小组函数共同完成某些目的,例如爬山。)

关于第 2 点,任何没有出现在正常百分比的堆栈样本上的代码,或者出现但显然不会从转换为 C 语言中受益的任何代码,例如 I/O。

关于第一个和第二个要点,我同意测量不是主要目标,而是寻找要优化的代码过程的副产品。提出这样的测量结果也是无关紧要的。

我也遇到过类似的情况,除了不是在python和C之间,而是在C和硬件之间。**

举个例子,如果总运行时间是 10 秒,并且算法大约有 50% 的时间在堆栈上,那么它负责大约 10 秒中的 5 秒。如果将算法转换为 C 会产生 10 倍的加速,那么 5 秒将缩短到 0.5 秒,因此总时间将缩短到 5.5 秒。(大致 - 实现时间减少比提前准确知道它将有多大更重要。)注意,此时,整个过程可以重复,并且将其他内容转换为 C 也可能有意义。当样本显示 python 代码正在做它擅长的事情,而 C 代码正在做它擅长的事情时,你可以停止这个过程。

** 例如浮点数学、库与芯片或图形、绘图文本和多边形。

于 2010-11-16T16:57:02.123 回答