资讯中心 Info
当前位置:酷叮猫 > 资讯中心 >
在 Python 内混用 C 语言
发布日期:2018-06-21 阅读次数:

  今天,我们来解决python的`速度`问题.我们平时所说的Python是指在PC机上的CPython,换句话说,Python的解释器是用C语言编写的.

  为Python编写C扩展模块能够显著提高Python的执行速度,眼下有好几种方案可以完成这件事。

  1. 使用Python自带的 ctypes 模块在Python内直接调用C的动态链接库代码,这对于调用现有的库,一些不开源的库很有用.

  2. 用Python自带的c API来写模块,当然是用c/c++来编写

  3. 用 Cython 的新语法来写扩展模块,这种新语法看起来既像Python又像C,是个语法混合体,但还有很多人推崇,   其优点是可以同时调用C函数和Python函数。但其语法小编着实看着头大,有兴趣的可以自行研究.

  4. 用wsig, sip, boost.python等这些老派方法,他们都有各自的专门的要求,小编没用过,就不妄下评论了。

  5. 使用pybind11来写Python扩展模块。这个好东西小编一定说几句,很值得一看,它只有头文件,用些简单的写法就可以封装C/C++的代码,待编译出动态链接库后,Python可以直接导入使用,小编曾在Mac OSX系统上写过pyOF库,封装了一个开源C++库的一部分代码,后来就没有时间弄了。推荐pybind11啊,它用来封装C++非常方便,大家可以到网上搜索一下。

  6. 使用 cffi 模块。它本是pypy的一部分,pypy就是一个高速版Python,这个cffi也支持CPython, 它是ctypes的替代方案,在Python内写C代码和调用C动态库代码,但是比ctypes更方便,干净。

  我们这里介绍的就是cffi, 它也是做 pyTorch 人工智能编程时官方推荐的使用方法。下面提供两段代码,分别是纯python编写,和使用cffi编写,算法都一样,函数做10000次递归,再重复1000次。

对比一下他们的执行速度。

  ======================= 纯 python 代码 =========================

  # coding:utf-8

  import sys

  sys.setrecursionlimit(10010)

  def factorial(n):

      'Compute a factorial of n'

      if n<=0:

          return 1

      else:

          return n + factorial(n-1)

  if __name__=='__main__':

      for i in range(1000):

          factorial(10000)

  ===================cffi 版本的 Python 代码 =========================

  # coding:utf-8

  from cffi import FFI

  ffibuilder = FFI()

  ffibuilder.cdef("unsigned long factor_cffi(unsigned long);")

  ff = ffibuilder.verify(r'''

      static unsigned long factor_cffi(unsigned long n) {

          if(n <= 0) {

              return 1;

          }else{

              return factor_cffi(n-1) + n;

          }

      }

  ''')

   

  if __name__=='__main__':

      for i in range(1000):

          ff.factor_cffi(10000)

  ==================== 运行时间对比 =================

  [Running] python "/home/xxx/dev/python/test.py"

  [Done] exited with code=0 in 9.829 seconds

  [Running] python "/home/xxx/dev/python/test_cffi.py"

  [Done] exited with code=0 in 0.14 seconds

  以上代码是在 Ubuntu 16 ,python 2.7下测试.

  我们可以看到这个例子中,使用cffi模块混入红色的 C 代码编程,使效率提升70倍,当然算法不同,参数不同都会引发对比结果的大幅变动,并不是绝对的,这个仅仅是给大家一个直观的感受.

  从以上代码就可以看出来,我们仅仅是混合了两种语言,并不需要学习第三方的专有语法,就可以调用C代码。当然cffi不止这一种用法。这里只给出一个最为直观的用法, 它运行时会在后台调用c编译器,我们也看不到编译过程。前提是你的机器上已经安装有C/C++编译器工具,python需安装cffi模块.

  在众多方法中,网上有评测显示 cff i并不是最快速的方法. 最接近原生Pytohn C API的方法才是提速最快的方法,但使用 Pytohn C API 的方法实在是很麻烦地,所以说,根据不同的场景选择最合适的就是最好的。

  对C语言,追求简单,上手快, 不用多学习,  懒人...... 我推荐 cffi,

  对C++语言,第三方C++库,  我推荐 pybind11。

课程体系
通知公告