第 7 章 编译为 C 语言 编译为 C 语言
本作品已使用人工智能进行翻译。欢迎您提供反馈和意见:translation-feedback@oreilly.com
要让代码运行得更快,最简单的方法就是减少代码的工作量。 假设你已经选择了好的算法,并减少了处理的数据量,那么执行更少指令的最简单方法就是将代码编译成机器码。
Python 为此提供了多种选择,包括基于 C 语言的纯编译方法,如Cython;通过Numba 进行的基于 LLVM 的编译;以及替换虚拟机PyPy,其中包括内置的即时 (JIT) 编译器。在决定采用哪种方法时,您需要平衡代码适应性和团队速度的要求。
每种工具都会给你的工具链增加一个新的依赖,Cython 要求你用一种新的语言类型(Python 和 C 的混合语言)编写代码,这意味着你需要一种新的技能。Cython 的新语言可能会影响团队的工作速度,因为不懂 C 语言的团队成员可能难以支持这种代码;但在实践中,这可能是一个小问题,因为你只会在代码中精心选择的小部分区域使用 Cython。
值得注意的是,对代码进行 CPU 和内存剖析可能会让您开始考虑可能应用的更高层次的算法优化。这些算法上的变化(例如避免计算的附加逻辑或避免重新计算的缓存)可以帮助您避免在代码中做不必要的工作,而 Python 的表达性可以帮助您发现这些算法机会。Radim Řehůřek在"Making Deep Learning Fly with RadimRehurek.com(2014)"中讨论了Python实现如何战胜纯C实现。
在本章中,我们将回顾以下内容:
-
Cython,最常用的 C 语言编译工具,涵盖
numpy和普通 Python 代码(需要一定的 C 语言知识) -
Numba,一种专门用于
numpy代码的新编译器 -
PyPy,一种稳定的非
numpy代码即时编译器,可替代正常的 Python 可执行文件
本章后面我们将介绍外来函数接口,它允许将 C 代码编译成 Python 的扩展模块。Python 的本地 API 可与 ctypes 或cffi (来自 PyPy 的作者),以及f2py Fortran 到 Python 的转换器一起使用。
可能获得什么样的速度提升?
如果您的问题适合编译方法,那么速度提高一个数量级或更多是完全可能的。在此,我们将介绍在单核上实现一到两个数量级的提速的各种方法,以及通过OpenMP 使用多核的方法。
编译后运行速度往往更快的 Python 代码是数学代码,它有很多重复相同操作很多次的循环。在这些循环中,您可能会创建大量的临时对象。
调用外部库的代码(如正则表达式、字符串操作和调用数据库库)在编译后不太可能有任何提速。受 I/O 约束的程序也不太可能有明显的速度提升。
同样,如果您的 Python 代码主要是调用矢量化的numpy 例程,那么编译后运行速度可能不会更快--只有当编译的代码主要是 Python 代码(可能主要是循环代码)时运行速度才会更快。我们在第 6 章中介绍了numpy操作 ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access