1、cython
人生苦短,我用python。
python简单易用,强大灵活,加之活跃的社区贡献了无数的开源库,备受广大程序员喜欢,但是速度上,相比于其他语言就落后许多,但作为胶水语言,它可以和c语言非常有效的结合,因此,我们可以使用c语言来为python加速。
cython是一种将python代码的编译器,它可以将纯python代码编译成c,不仅如此,它还允许我们写出python和c的混合代码。
2、一段纯python代码
下面是一份纯python代码,计算斐波那契数列
# coding=utf-8
import time
def fib(n):
if n == 0:
return 0
if n == 1:
return 1
return fib(n-1)+fib(n-2)
t = time.time()
fib(40)
print(time.time() - t)
上面的这段代码在我的mac上执行需要60秒
3、使用cython来加速
3.1 新建一个名为fib.pyx的文件,内容为
def fib(n):
if n == 0:
return 0
if n == 1:
return 1
return fib(n-1)+fib(n-2)
3.2 新建一个名为fib_setup.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("myfib", ["fib.pyx"])]
)
3.3 编译fib.pyx
执行命令 python fib_setup.py build_ext --inplace, 在目录下会生成一个名为myfib.so的文件和一个fib.c的文件
3.4 调用myfib.so
新建一个名为cython_fib.py的文件,内容为
# coding=utf-8
import myfib
import time
t = time.time()
myfib.fib(40)
print(time.time() - t)
执行这段代码,仅仅需要16秒,然而在3.1步骤中,我没有改变任何代码,仅仅是在3.3步骤中将其编译成了so文件
在这个过程中,我们将python代码编译成了c的代码,显然,c语言的速度更快
3.5 增加类型注解
将fib.pyx的内容修改为下面的
def fib(int n):
if n == 0:
return 0
if n == 1:
return 1
return fib(n-1)+fib(n-2)
然后重新编译,重新执行cython_fib.py,执行时间降为13.5秒,相比于3.4步骤中的16秒,又减少了2.5秒
代码里所使用的是高层的python对象,需要把这些对象转换为本地c对象,而在进行数值方面的编码时,有需要把结果转回python对象,这个过程中就回调了python虚拟机,而如果标注了变量的类型(int n) ,那么就不需要在回调python栈了,这样速度会更快。
但这还不是终极速度
4、直接调用c的代码
4.1 新建一个名为c_fib.c的文件,内容如下
#include "stdio.h"
static int c_fib(int n){
if(n==0)
return 0;
if(n==1)
return 1;
return c_fib(n-1)+c_fib(n-2);
}
4.2 修改fib.pyx的内容
cdef extern from "c_fib.c":
int c_fib(int n)
def fib(n):
return c_fib(n)
重新编译,再次执行,仅仅需要1秒钟的时间