最新消息:

Cython快速实现Python的C重构

python admin 4200浏览 0评论

说起Python,首先想到的他是一种“胶水语言”。作为一种合格的胶水语言,比起开发的难易程度或者开发效率来讲,语言的适应性和可扩充性同样很重要。python的一大特色是有许多方便灵活的扩展模块。

对于上次我们曾经说过ctypes的方式可能对于已经存在的lib库,这对于已经存在的C libs或者有C程序员参与的情况下是很方便的,但对于很多团队来说,合格的C程序员始终是个缺口。这次我们就说说针对单独的一个模块通过Python的一个扩展Cython进行C重构,从而达到尽可能减少工作量,从而达到最便捷的C重构。

 

在此之前,安装cython和python-dev(需要Python.h文件参与)

apt-get install python python-dev

python原文件,这次选择的是“费波拉契数列”的计算:

fib.py

def fib(i):
    a = 0
    b = 1
    while i > 0:
        i -= 1
        a, b = b, a+b

    return True
startTest.py
import time
from fib import fib

startTime = time.time()
for i in xrange(1,10):
    fib(10**6)

print time.time() - startTime

执行 python startTest.py得到的运行时间是130.857528925,两分多钟。

准备编译脚本,虽然违背了没有coding,但请相信,代码真的很少

build.py

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

setup(

cmdclass = {'build_ext': build_ext},

ext_modules = [Extension("fib", ["fib.py"])]

)

开始编译:

root@Vhost2:~/testCython# python build.py build_ext --inplace
running build_ext
cythoning fib.py to fib.c
building 'fib' extension
creating build
creating build/temp.linux-x86_64-2.7
gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c fib.c -o build/temp.linux-x86_64-2.7/fib.o
gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions build/temp.linux-x86_64-2.7/fib.o -o /root/testCython/fib.so

当前目录下应该多出来一个fib.c和fib.so,不要怀疑,.c的那个就是C的源码,而.so则是基于c 的python 扩展。如果你有实力可以在.c文件上进行人肉优化,我想效率也远高于从0开始。其中比较好的一点是,C源码中,python的源码会作为注释添加其中,看起来也很方便。

本文主要介绍的是cython,对于生成出来C代码的优劣不在讨论中,有兴趣欢迎私下交流。

开始新的测试:

删除原来的py库,mv fib.py fib.py.bak && rm -f *.pyc

python startTest.py

得出结果105.579359305,汗!没有想象中的那么突飞猛进。通过cProfile的导出,没有看出什么名堂。
python

C

事实上查看了C源码,发觉事实上大量的代码实现的仍旧是Python的逻辑,而Python的效率跟C绝对不是一个等级。这当然存在更加有优势的优化方式,但已经脱离了“快速实现”的本质,本文不再介绍。

考虑到“费波拉契数列”是python实现的经典例子,我重新改动了代码。(方便测试,连函数名都没动,容易误导)

fib.py

def fib(i):
    a = 0

    while i > 0:
        a += i
        i -= 1

return a

6.1317088604 : 4.3963329792算是比较显著了吧。

对于编译后的脚本来说,个人觉得性能的提升只是一方面的优势。特别是一些对安全性有要求的应用中,编译后的代码隐蔽性较好,在生产环境中即便别人获得了你的服务器权限,也很难反拆你的算法,避免了很多麻烦。

需要注意的是,对于yield方式实现的迭代器,cython无法完成编译,只能重新修改代码,但对于大多数的代码来说,cython几乎是平滑的。而且你甚至可以写一个全自动的部署脚本,上线后自动完成编译。

转载请注明:爱开源 » Cython快速实现Python的C重构

您必须 登录 才能发表评论!