要使用cython首先得有的她的环境 [ 废话,^_^ ],系统上有pip包管理环境的话直接:pip install cython 即可安装cython或者也可以源码安装:
https://github.com/cython/cython/wiki/Installing
Cython code must, unlike Python, be compiled. This happens in two stages:
一个简单的Python计算方法,python_evaluate.py:
import math
def my_evaluate(a ,b):
x = math.pi/180.0
c = math.sin(a*x) + math.cos(b*x)
r = math.sin(c*a) + math.cos(c*b)
return r
python_evaluate.py对应的cython文件python_evaluate.pyx:
cimport cython
python_evaluate.pyx
cdef extern from "math.h":
float cosf(float theta)
float sinf(float theta)
cdef float _my_evaluate(float a,float b):
cdef float pi = 3.14159265
cdef float x = pi/180.0
cdef float c = sinf(a*x) + cosf(b*x)
cdef float r = sinf(c*a) + cosf(c*b)
return r
def my_evaluate(float a,float b):
cdef float x = _my_evaluate(a, b)
return x
注意这里使用cdef extern 的方式使用从指定头文件声明函数(在此就是使用C标准库的math.h,而非Python库中math)。
Cython 程序需要先编译之后才能被 Python 调用,具体步骤是:
要完成前两步,linux和Windows上有点不太一样分别说明下吧[其实就是生成的最终文件不一样 ^_^]:
linux和Windows 都可以用下面的setup.py生成动态库供Python调用:
# setup.py
#python setup.py build_ext --inplace
from distutils.core import setup, Extension
from Cython.Build import cythonize
import numpy
setup(ext_modules = cythonize(Extension(
'cython_evaluate',
sources=['cython_evaluate.pyx'],
language='c',
include_dirs=[numpy.get_include()],
library_dirs=[],
libraries=[],
extra_compile_args=[],
extra_link_args=[]
)))
解释下相关参数:
执行下面命令就可以把 Cython 程序编译成动态链接库:
python setup.py build_ext –inplace
当运行成功后,可以看到在当前目录多出来了 cython_evaluate.c (是cython根据cython_evaluate.pyx生成的 C 程序)和 cython_evaluate.so(一个动态链接库),还有一个build目录。
调用time_cmp.py 对Python和cython的计算时间进行对比。
import timeit
a, b = 30, 60
num = 8000000000
t_python = timeit.Timer("python_evaluate.my_evaluate(%f,%f)" % (a,b),"import python_evaluate")
t_cython = timeit.Timer("cython_evaluate.my_evaluate(%f,%f)" % (a,b),"import cython_evaluate")
print "python function", t_python.timeit(10000), "sec"
print "cython function", t_cython.timeit(10000), "sec"
运行结果:
python time_cmp.py
python function 0.0105509757996 sec
cython function 0.00193190574646 sec
可见,虽然这个Python模块计算模块比较简单,但是用cython重写下性能提升还是有的~~~
为了解释setup.py的原理,写了个用gcc分步骤编译的脚本build.sh:
#!/bin/bash
# This shell is used to explain how cython setup.py works.
#
if [ $# -ne 1 ];then
echo "parameters error!!"
echo "usage: $0 XXX { The name of XXX.pyx, exclude .pyx}"
echo "e.g.:sh build.sh cython_evaluate"
exit 1
fi
name=$1
python_inc=`ls /usr/include/ | grep python`
echo "python headers:$python_inc"
# Will create a ${name}.c file
cython ${name}.pyx
# Compile the object file
gcc -c -fPIC -I/usr/include/${python_inc}/ ${name}.c
# Link it into a shared library
gcc -shared ${name}.o -o ${name}.so
这个脚本其是就是官方文档中所提到的第三种方法,“There are several ways to build Cython code:”
Run the cython command-line utility manually to produce the .c file from the .pyx file, then manually compiling the .c file into a shared object library or DLL suitable for import from Python. (These manual steps are mostly for debugging and experimentation.)
运行脚本:
sh build.sh cython_evaluate
同样也能生成供Python调用的动态链接库cython_evaluate.so。
其实Windows下和Linux下的基本差不多,cmd,运行如下命令:
d:\Python27\python setup.py build_ext –inplace
d:\Python27\python 这个是我的Windows上python可执行程序的绝对地址。最终生成俩文件:cython_evaluate.c,cython_evaluate.pyd,这个cython_evaluate.pyd文件和Linux上的XX.so文件相当,Python 解释器载入会载入这个文件从而找到我们的函数实现。
Cython 中类型声明非常重要,但是我们不加类型标注它依然是一个合法的 Cython 程序(这样的又变成Python动态类型的问题,很多编译期间就能确定下来的事情被推到了运行时,性能会打折扣), Cython 提供了一个很好的工具,可以方便地检查 Cython 程序中哪里可能可以进一步优化。下面命令既可以对 XX.pyx 进行分析:
cython -a cython_evaluate.pyx
如果当前 Cython 程序用到了 C++,则需要加上 –cplus 参数。在成功运行完 cython -a 之后,会产生同名的 .html 文件,如下图:
网页最上面与说明,黄色部分标识了和 Python 发生交互的地方,点击每一行可以查看相应的生成的 C/C++ 代码。本Bolg相关代码见:github。