前言
注意以下内容均为本人主观操作感受,运行环境为Win10+python3.7_32位,仅供本人日后查阅
众所周知,python是一门优美而简洁的编程语言,其最大的不足在于运行速度过于感人,而C语言作为最接近底层的高级语言,速度快是他最大的优势。python被誉为胶水语言,应该有办法和C语言胶和起来,我查阅资料发现python调用C语言最普遍的方式大概有三种:
将C语言的函数编译成dll动态链接库,然后通过python的ctypes模块对dll进行调用。
借由cython先将python代码编译成C语言代码,然后再讲C代码编译成.pyd文件直接在python中导入进行调用,cython本身有一定语法,不过不会一般也不太影响使用。
使用Swig可以将C代码直接封装成python代码,过程略为复杂,优点是可以为多种语言提供接口。
以上几种方法的原理和过程下图很好的解释了:
本文以斐波拉契函数为例,探究python和C的合璧之法。
通过运行上面的代码可以得到运行时间:
纯python:
计算结果:102334155
python time cost: 87.49325394630432
纯C语言:
计算结果:102334155
C cost time:0.863000
差不多差了两个数量级吧。。。
1. 通过ctypes调用dll
首先得先生成一个dll,你可以在ide里新建一个dll工程进行创建。更简单的做法是利用下面的gcc命令直接在cmd里进行编译,但前提是你已经装了Mingw或者并Mingw-w64且设置了环境变量,其中有个比较坑的地方就是你编译出来的dll位数要和你的python位数要匹配,像我笔记本上装的是Mingw-w64,而pyhton是32位的,32的python无法调用64位的dll,而这位Mingw-w64虽说同时支持64位和32位,但是前提是安装时勾选的是sjlj而不是seh,seh不支持32位!
安装Mingw-w64可以参考:Mingw-w64安装
用于编译dll的c语言代码只需给出函数就好了:
下面是cmd中将C原文件编译成dll的命令:
gcc -fPIC -shared name.c -o name.dll
如果是sjlj的Mingw-w64加上-m32可以编译出32位dll:
gcc -fPIC -shared -m32 name.c -o name.dll
然后在python中导入ctypes模块就可以调用dll了:
ctype调用dll运行时间:
计算结果:102334155
dll time cost: 0.9999649524688721
因为只有一个函数,还调用的是C语言的,所以速度和纯C差不多。
2. cython
先给出官方的一个教程:官方教程
使用cython首先要安装cython模块:
pip install Cython
然后你需要安装Mingw进行一番配置或者直接下载安装Visual Studio安装C++环境,因为我用的是Mingw-win64,所以自然就先抛弃后面那个巨无霸选用前者,一番尝试后发现还是Visual Studio真香。当然可能单纯的是因为Mingw-win64不支持而已,用Mingw的话应该是可以的(但愿)。
安装完环境后就可以直接把之前的纯python代码中的函数部分进行cython转换,不过需要现将其后缀名改为.pyx,然后需要再创建一个setup.py文件,其中写入代码:
然后还是cmd中执行:
python setup.py build_ext --inplace
这时应该会生成一个.pyd文件,这个文件本质和前面的dll应该差不多,可以通过import在python中使用:
运行结果:
计算结果:102334155
cython time cost: 15.108871698379517
可以看到即使是在没有使用任何cython语法的情况下,cython的加速能力也是令人惊叹的,运行速度提高了一个数量级左右!
3. Swig
同样先给出一个教程参考:Swig教程
其实swig的原理和前面也差不多,但是过程更为复杂。首先当然要安装swig,下载解压后同样添加到系统环境变量。
然后要准备的有C语言源文件,一个.i文件,还有一个setup.py文件。
最后在命令行运行setup.py:
python setup.py build_ext --inplace
最后生成的文件中应该有一个python文件,可以直接进行调用,除此之外我发现还有一个.pyd文件,果然和前面的方法都差不多呢,导入运行方法也和之前相同。
运行结果:
计算结果:102334155
swig time cost: 0.6825790405273438
居然比纯C语言还要快!大概是因为去掉了计时模块的缘故,可能python的计时模块比C的要快?结果还是很匪夷所思呢?
namba加速不同于以上3种方法,上面3种方法多多少少会和C语言扯上点关系。numba则是直接在python源文件里通过加上一些代码直接运行并获得加速效果,本质原理也是使数据向静态靠拢,但是实现过程与上面3种方法相比更简单,可以参考官方入门教程
下面具体看一下实现过程:
首先肯定是要先安装numba包
pip install numba
然后只需在Python代码中导入numba并用jit修饰相应的函
运行结果:
计算结果:102334155
[email protected] time cost: 1.2832109928131104
加速效果可以说是相当惊人的,比cython要快,而且操作也特别简单,不用导来导去,和numpy相配合使用可以使运行速度得到极大的提升。
总结方案
运行时间
纯Python
87.49325394630432
纯C语言
0.863000
ctypes
0.9999649524688721
cython
15.108871698379517
swig
0.6825790405273438
numba
1.2832109928131104
python结合c语言的三种方法中ctypes方法最简单,将C代码直接编译成dll即可使用,cython可以为现有的python代码加速,swig可以直接将C转换为python,就是有点麻烦,但速度是最快的。numba的jit加速比上面三种方法都要更简单,只需在python源码里加几句就行了,而且速度也很可观。