加速python,保护你的源代码 cython
http://bbs.chinaunix.net/thread-4149295-1-1.html
本帖最后由 cdhigh 于 2014-08-07 18:46 编辑 加速python,保护你的源代码 =========================== 1. 背景 最近一个项目需要DTMF解码,使用到傅立叶变换的一种变种:Goertzel算法,这是计算密集型算法, 尽管Goertzel算法已经将基本傅立叶变换大大简化,但是其计算量还是比较大,使用python实现后效率较低,要几秒才能计算出一个完整的电话号码串,所以不能实际应用。 碰到此情况一般第一考虑是将Goertzel算法使用C/C++实现,然后python调用,但是此项目我希望更pythonic一点,也方便以后维护,结果多方抉择选中了cython方案。 2. cython简介 cython网上有很多介绍和教程之类的,我就不赘述了,简单“科普”一下。 cython是python的一个扩展模块,主要功用是将python代码编译成C/C++,然后再编译成python扩展模块(windows上是*.pyd)。 cython的最简单用法就是将”任何“合法的python代码直接编译为pyd,则其中的代码不经python解析器而直接调用python的api,这样你就可以隐藏你的源代码了,并且也获得了一点点的效率提升(我实际测试大约能提高10%)。 次简单用法就是将你的python代码中没有使用到动态特性的变量使用cython语法声明为静态类型,这样你就可以用对源代码进行最小的改动,获得很大的效率提升,而且代码可读性没有任何影响,还是“python代码”。 真实的案例是我将python写成的DTMF解码模块仅是将变量切换为静态类型后,效率提升*30倍*,最终的pyd模块的效率已经和C++的实现差别不大,~200ms能完整解出一个完整的号码串,不管是离线应用或在线应用都满足需求,所以我就没有再进一步的优化了,在花大力气之后即使能优化成100ms,0.1s和0.2s的区别在我的应用中不是人能感知的。 3. cython语法(通过一些代码片段管中窥豹) cython文件一般后缀为pyx(还有pxi/pxd) cython语法代码前要增加cython标识,比如:cdef, cpdef等。 1. 变量声明
2. 类实例变量声明 使用cdef将所有实例变量在正常的类变量位置先声明,然后在__init__()中初始化 有code有真相: ------------
3. 让cython函数可以被其他模块的python代码调用 将函数声明为cpdef即可,如果声明为cdef则为纯粹的c函数,其文档介绍即使将函数声明为cpdef,如果是其他c函数调用(包括cdef定义的函数),则cython会优化为cdef,效率也很高 -----------
4. 使用数组
5. 循环优化 可以放心的使用range循环,cython会将其优化为c类型的for语句形如: for (i = 0; i < 100; i++) 或者你也可以使用cython特有的语法:
6. 使用c/c++标准库函数
7. 直接调用c/c++源文件中的函数或类(python/cython/c混合编程)
4. 编译pyx 1. 安装cython和编译cython文件都需要c/c++编译环境, 如果你安装了VS,则一般不用更多设置, 如果没有,在windows环境下建议安装Mingw,安装完成后将c:\MinGW添加到path系统变量,然后在C:\PythonXX\Lib\distutils\ 中添加一个 distutils.cfg文件,内容为:
2. 安装完cython后,如果C:\PythonXX\Scripts没有在path系统变量,也建议添加 3. 直接执行 cython yourfile.pyx 则生成 yourfile.c 文件,然后使用编译器编译连接即可,稍复杂,网上很多教程,我就不再重复了,我这里说的是简单的方法 4. 新建一个setup.py (名字可以随便起) :
5. 执行命令:
则在yourfile.pyx 同一目录下生成yourfile.pyd 6. 使用yourfile.pyd和yourfile.py一样,没有任何区别,
7. cython -a youfile.pyx 则生成yourfile.c的同时还会生成yourfile.html文件,列出cython代码行和c代码行的一一对应关系,点击代码行则显示对应的c代码,特别方便进行代码优化。 5. profiling 使用cython的目的是效率,你肯定关心cython究竟给我提高了多少效率,所以“测速”的功能肯定是不能缺的。 1. 在pyx文件的头两行内添加一行:
2. 测试代码:
则打印出每个函数的调用次数和执行时间等内容 注意在发行你的软件时切换profile=False或删除此行 6. 结束语 cython是不是很帅?python的开发效率,c的执行效率! 使用cython消除程序热点(效率瓶颈)和隐藏核心代码,通过 py2exe/cx_freeze 之类的打包软件将你的程序打包,然后就可以放心的发布你的软件了。 7. 再结束:和nuitka对比 除cython外,nuitka可以将全部代码都转换成C++代码然后编译,不过nuitka是直接调用python的api,不像cython,生成的是真正独立的c代码,可以不调用python的api高效率的实现一些计算密集任务,所以我还是推荐cython,而不是nuitka。 |