您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Python

猛踩油门!令Python加速

时间:2020-06-16 10:36:32  来源:  作者:

先要能做,做得对,最后才是要做得快。

——Kent Beck

这篇附录将致力于提供一些优化代码的工具,以便能使我们的代码变得更简洁,或者更快速。尽管此类优化在大多数情况下并不能代替算法设计(特别是当我们所处理的问题规模非常大的时候),但是让我们的程序运行快上10倍应该还是能做到的。

在调用外部辅助之前,我们应该首先审视一下自己是否已经做到Python的内置工具物尽其用了。在本书中,我曾列举过许多类似的例子,其中包括了适用于双向队列的deque,以及如何在合适的条件下运用bisect和heapq来提升算法的性能。另外,作为一个Python 程序员,我们也很幸运Python提供了当今最高级也最为有效的排序算法(list.sort(),并且高效地实现了它),以及一个功能多样而又迅速的散列表(dict)。甚至您还会发现,itertools与functools模块中也能给我们带来某种程度的高性能代码1。

除此之外,当我们选择要用外部库来优化代码时,还应该先确认一下这种优化是否有必要。优化本身也往往会让我们的代码变得更复杂,依赖关系更多,所以优化之前要想一想,优化是否真的值得。如果您的算法已经“足够好”,代码也“足够快”,那么通常就不值得引入用其他语言(如C语言)撰写的外部模块了。当然,什么是“足够好”、“足够快”,也取决于我们自己的判断。(您可以在第2章找到一些用于代码测速与剖析的例子。)

需要注意的是,本篇附录中所讨论的包和外部扩展库主要用于优化单处理器的代码,其中既包括高效的函数实现,也包括封装好了的扩展模块,以及速度更快的Python解释器。当然,考虑将我们代码改为多处理器版本确实能有助于大幅提高运行效率,所以您真的想这么做的话,multiprocessing模块是一个好的开始。如果您希望深入了解多核编程,您同样可以找到非常多的关于分布式计算的第三方工具。例如,您可以查看一下Python wiki上Parallel Processing页面中的内容。

在接下来的内容中,我们将会看到一份加速工具的选单。其中包含了业界在若干个方向上的努力,应对于各种情境的变化,毕竟新项目会与时俱进,而一些旧项目则逐渐被淘汰。如果您对下面所介绍的工具方案很感兴趣,打算将其运用到自己的项目来,我们建议您可以先浏览一下这些扩展库的网站以及社区——当然,这要根据您自己的需要,本篇附录最后附有这些网站的地址(见表A-1)。

NumPy、SciPy、Sage与Pandas:NumPy是一个历史悠久的包。它起源于Numeric和numaray这些更为古老的项目。NumPy的核心是一个多维数字数组的实现。除了该数据结构外,它还实现了若干个函数与运算符,它们能够高效地进行数组运算,并且对函数被调用的次数进行了精简。您可以用它来进行极其高效的数学运算,而无需对内置模块进行任何额外的编译。SciPy和Sage则属于那种更为宏大的项目,它们将NumPy内置为自身的一部分,同时内置了几种不同的工具,实现了用于特定科学、数学及高性能计算的模块(关于这些内容,我们在后面的内容中还会提到)。Pandas是一个侧重于数据分析的工具,但只有等它的数据模块适用于我们的问题实例时,它才是一个强大而快捷的工具。另一个与之相关的工具叫Blaze,它在我们处理大量半结构化数据的时候是非常有用的。

PyPy、Pyston、Parakeet、Psyco与Unladen Swallow:让代码运行得更快,且侵入性最小的方式之一就是使用实时编译器(just-in-time (JIT) compiler)。在以前,我们可以用Python安装器来安装Psyco。安装完成之后,我们就只需要直接导入psyco模块,然后调用psyco.full(),代码的运行速度就会有明显的提升。在您运行Python程序时,Psyco会将我们的一部分代码编译为机器码。而由于它可以在运行时监控程序,因此也就可以做出某些静态编译器无法做到的优化。例如,一个Python list中可以包含任意类型的值,但当Psyco注意到该list其实只包含整型时,它就会假设,可能该list在之后的运行时间里也仅会包含整型,因而对相关代码进行编译,将该list编译为整型列表。遗憾的是,如今包括Psyco在内的数个类似的Python加速器项目以及它们的网站都已经处于“停止维护以及消亡”的状态了,尽管类似的功能在PyPy中得到了传承。

PyPy则是一个更为宏大的项目:它用Python语言重新将Python实现了一遍。当然,这本身不会直接加快运行速度,这么做主要是为便于代码的分析、优化与翻译。正是基于这个框架,JIT编译才变为了可能(这使得我们不再需要Psyco,代码在PyPy内就能完成编译)。甚至PyPy还能将代码翻译成像C那样的、性能更高的编程语言。另外,在PyPy中所实现的Python的核心子集被称为RPython(restricted Python),这部分已经有工具可以静态地编译成高效的机器码。

在某种程度上,Unladen Swallow也是一种Python的JIT编译器。或者更精确地说,它是Python解释器的一个版本,被称为底层虚拟机(Low Level Virtual machine,LLVM)。该项目的目标是将加速因子相对标准编译器提高至5。然而,Unladen Swallow项目还没有达到这个目标,但它的开发活动似乎已经停止了。

Pyston也是一个由Dropbox开发的、与LLVM平台较为接近的Python JIT编译器。在本书写作期间,Pyston还是一个非常年轻的项目,只支持了语言的一个子集,并且完全不支持Python 3。然而在很多情况下,它已经优于Python的标准实现,并且目前还在积极地开发中。此外,Parakeet也是一个相当年轻的项目,用该项目Web页面的话说,“其中包含了类型接口、并行数据的数组操作以及大量能使代码加速的黑魔法”。

GPULib、PyStream、PyCUDA与PyOpenCL:这四个包都是在用图像处理单元(graphics processing units,GPUs)来实现代码的加速。它们与Psyco这样的JIT编译器不一样,后者是通过代码优化来实现加速的。但如果我们有一个强大的GPU的话,为什么不用它来进行计算呢?比起GPULib,PyStream更加古老一点,而Tech-X公司已经转向了更为年轻的GPULib项目的开发。它提供了基于GPU的各种形式的数值计算。另外,如果您想用GPU来加速自己的代码,PyCUDA、PyOpenCL这两个项目也值得您试试看。

Pyrex、Cython、Numba与Shedskin:这四个项目都致力于将Python代码翻译为C、C++及LLVM代码。其中,Shedskin会将Python代码编译为C++程序,而Pyrex和Cython(后者实际上是前者的一个分支)的编译目标主要是C语言。另外,当我们用Cython(及其前身Pyrex)来进行编译时,我们可以在代码中加入一些可选的类型声明,例如静态声明一个整型变量之类的。此外,Cython还有NumPy数组的额外支持,这使您可以写出某种针对底层逻辑的代码,以高效操作数组内容。我在自己的代码中使用了这个特性,其中的部分代码的加速因子提升到300至400。而且,由Pyrex和Cython生成的代码可以直接编译为Python扩展模块,然后在Python代码中导入即可。如果您想从Python程序中生成出通用的C代码,Cython也依然是一种安全的选择。而如果您只是在寻找一种加速方式,特别是在面向数组与数学计算的代码的时候,或许Numba是一个值得看看的选择。它在被导入时会自动生成相应的LLVM代码。其升级版本NumbaPro还提供一些更为高级的功能,甚至还包含了对GPU的支持。

SWIG、F2PY与Boost.Python:这些工具可以帮助您将其他语言封装为Python的模块。它们所封装的语言分别是:C/C++,Fortran,C++。尽管我们也可以自行编写访问扩展模块的代码,但使用这些工具可以帮助我们免于许多单调乏味的工作——而且它们也更能确保结果的正确性。以SWIG为例,您只需要启动一个命令行工具,往里输入C(或C++)的头文件,封装器代码就自动生成了。SWIG的另一个优点在于,除了Python,它还可以成为很多语言的生成封装器。例如,您同样也能轻易地利用JAVAphp这样的语言来编写相关的扩展。

ctypes、llvm-py与CorePy2:这些模块可以帮助我们实现对Python底层对象的操纵。ctypes模块可用于在内存中构建编译C的对象,并且调用某些共享库中(如某些DLL)的C函数。而llvm-py包则正如之前所说,主要提供了LLVM的Python接口,以便于我们可以构建代码,然后更高效地编译它们。甚至如果您愿意的话,也可以在Python中用它来构建您自己的编译器(没准能搞出一种属于自己的编程语言!)。CorePy2也一样,它可以帮助您处理与高效运行代码对象,只不过,它是运行在汇编层的。(值得注意的是,ctypes如今已是Python标准库的一部分了。)

Weave、Cinpy与PyInline:通过这三个包,我们就可以在Python代码中直接使用C语言(或其他语言)。虽然不同的语言被混排在了一起,但代码仍然可以保持干净整洁,因为您可以使用Python字符串的多行特性,将C代码部分按照其自身的风格来排版。然后就能即时进行编译,并输出可用在Python代码中的代码对象。这样,我们就可以像使用ctypes模块那样使用它们了。

其他工具:显然,可用的工具远远不止这些,我们可以根据自己的需要来选择更多的工具。例如,如果我们希望节省的是内存而不是时间,那么JIT就不太适合了——JIT通常都需要耗费大量的内存。这时候,我会建议您去看看Micro Python项目。这是一个专为最小内存占用,使用Python的微控制器及嵌入式设备而设计的编程环境。而且,谁知道呢?也许我们有些时候根本不想用Python。或许我们只是在某种Python环境中工作,然后想使用某种高级编程语言,但同时希望自己所有代码都能运行得飞快,这时我会建议您看看Julia这个项目。尽管这项目在Python体系中算是个异类,实际上是一种不同的语言,但它的语法对于所有Python程序员来说都会感觉很熟悉。同时它也支持Python库的调用,这意味着Julia团队与Python项目之间一直有着密切的合作,例如IPython项目等2,甚至这一直是SciPy项目研讨会上的主题之一3。

表A-1 各加速器工具网站的URL

猛踩油门!令Python加速

 

本文摘自《Python算法教程》中的附录A

 

Python是一种面向对象、解释型计算机程序设计语言,其应用领域非常广泛,包括数据分析、自然语言处理、机器学习、科学计算以及推荐系统构建等。

本书用Python语言来讲解算法的分析和设计。本书主要关注经典的算法,但同时会为读者理解基本算法问题和解决问题打下很好的基础。全书共11章。分别介绍了树、图、计数问题、归纳递归、遍历、分解合并、贪心算法、复杂依赖、Dijkstra算法、匹配切割问题以及困难问题及其稀释等内容。本书在每一章结束的时候均有练习题和参考资料,这为读者的自我检查以及进一步学习提供了较多的便利。在全书的最后,给出了练习题的提示,方便读者进行查漏补缺。 本书概念和知识点讲解清晰,语言简洁。本书适合对Python算法感兴趣的初中级用户阅读和自学,也适合高等院校的计算机系学生作为参考教材来阅读。



Tags:Python加速   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
先要能做,做得对,最后才是要做得快。——Kent Beck这篇附录将致力于提供一些优化代码的工具,以便能使我们的代码变得更简洁,或者更快速。尽管此类优化在大多数情况下...【详细内容】
2020-06-16  Tags: Python加速  点击:(33)  评论:(0)  加入收藏
▌简易百科推荐
大家好,我是菜鸟哥,今天跟大家一起聊一下Python4的话题! 从2020年的1月1号开始,Python官方正式的停止了对于Python2的维护。Python也正式的进入了Python3的时代。而随着时间的...【详细内容】
2021-12-28  菜鸟学python    Tags:Python4   点击:(1)  评论:(0)  加入收藏
学习Python的初衷是因为它的实践的便捷性,几乎计算机上能完成的各种操作都能在Python上找到解决途径。平时工作需要在线学习。而在线学习的复杂性经常让人抓狂。费时费力且效...【详细内容】
2021-12-28  风度翩翩的Python    Tags:Python   点击:(1)  评论:(0)  加入收藏
Python 是一个很棒的语言。它是世界上发展最快的编程语言之一。它一次又一次地证明了在开发人员职位中和跨行业的数据科学职位中的实用性。整个 Python 及其库的生态系统使...【详细内容】
2021-12-27  IT资料库    Tags:Python 库   点击:(2)  评论:(0)  加入收藏
菜单驱动程序简介菜单驱动程序是通过显示选项列表从用户那里获取输入并允许用户从选项列表中选择输入的程序。菜单驱动程序的一个简单示例是 ATM(自动取款机)。在交易的情况下...【详细内容】
2021-12-27  子冉爱python    Tags:Python   点击:(4)  评论:(0)  加入收藏
有不少同学学完Python后仍然很难将其灵活运用。我整理15个Python入门的小程序。在实践中应用Python会有事半功倍的效果。01 实现二元二次函数实现数学里的二元二次函数:f(x,...【详细内容】
2021-12-22  程序汪小成    Tags:Python入门   点击:(32)  评论:(0)  加入收藏
Verilog是由一个个module组成的,下面是其中一个module在网表中的样子,我只需要提取module名字、实例化关系。module rst_filter ( ...); 端口声明... wire定义......【详细内容】
2021-12-22  编程啊青    Tags:Verilog   点击:(8)  评论:(0)  加入收藏
运行环境 如何从 MP4 视频中提取帧 将帧变成 GIF 创建 MP4 到 GIF GUI ...【详细内容】
2021-12-22  修道猿    Tags:Python   点击:(6)  评论:(0)  加入收藏
面向对象:Object Oriented Programming,简称OOP,即面向对象程序设计。类(Class)和对象(Object)类是用来描述具有相同属性和方法对象的集合。对象是类的具体实例。比如,学生都有...【详细内容】
2021-12-22  我头秃了    Tags:python   点击:(9)  评论:(0)  加入收藏
所谓内置函数,就是Python提供的, 可以直接拿来直接用的函数,比如大家熟悉的print,range、input等,也有不是很熟,但是很重要的,如enumerate、zip、join等,Python内置的这些函数非常...【详细内容】
2021-12-21  程序员小新ds    Tags:python初   点击:(5)  评论:(0)  加入收藏
Hi,大家好。我们在接口自动化测试项目中,有时候需要一些加密。今天给大伙介绍Python实现各种 加密 ,接口加解密再也不愁。目录一、项目加解密需求分析六、Python加密库PyCrypto...【详细内容】
2021-12-21  Python可乐    Tags:Python   点击:(8)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条