cython的使用

0. 环境配置

要使用cython首先得有的她的环境 [ 废话,^_^ ],系统上有pip包管理环境的话直接:pip install cython 即可安装cython或者也可以源码安装:
https://github.com/cython/cython/wiki/Installing

1. 相关介绍:

  • Cython 编译器把 Cython 代码(格式为XX.pyx)编译成 C/C++ 代码,然后把生成的C/C++代码编译成动态链接库(Linux上的XX.so动态库文件,Windows上对应的是XX.pyd文件),这个动态链接库可以被Python解释器直接加载使用,从而调用Cython相关模块,引用下官方文档的话:

    Cython code must, unlike Python, be compiled. This happens in two stages:
  • A .pyx file is compiled by Cython to a .c file, containing the code of a Python extension module
  • The .c file is compiled by a C compiler to a .so file (or .pyd on Windows) which can be import-ed directly into a Python session.
    There are several ways to build Cython code:
  • Write a distutils setup.py. This is the normal and recommended way.
  • Use pyximport, importing Cython .pyx files as if they were .py files (using distutils to compile and build in the background).
  • 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.)
  • Use the [Jupyter] notebook or the [Sage] notebook, both of which allow Cython code inline.

2. cython使用示例:

一些基本概念:
  • Cython 程序的扩展名是 .pyx
  • cimport 是 Cython 中用来引入 .pxd 文件的命令
  • Cython 的函数使用 cdef 定义,并且他可以给所有参数以及返回值指定类型。

一个简单的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 调用,具体步骤是:

  • Cython 编译器把 Cython 代码(格式为XX.pyx,这个文件可以调用Python或C\C++相关函数)编译成 C/C++ 代码;
  • 把生成的代码编译成动态链接库(Linux XX.so or Windows XX.pyd )
  • Python 解释器载入动态链接库

要完成前两步,linux和Windows上有点不太一样分别说明下吧[其实就是生成的最终文件不一样 ^_^]:

1. Linux

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_evaluate’ 是我们要生成的动态链接库的名字
  • sources 里面可以包含 .pyx 文件,以及后面如果我们要调用 C/C++ 程序的话,还可以往里面加 .c / .cpp 文件
  • language 其实默认就是 c,如果要用 C++,改成 c++
  • include_dirs 这个就是传给 gcc 的 -I 参数(numpy.get_include()其实这个只是示例,本程序不需要)
  • library_dirs 这个就是传给 gcc 的 -L 参数
  • libraries 这个就是传给 gcc 的 -l 参数
  • extra_compile_args 就是传给 gcc 的额外的编译参数,比方说你可以传一个 -std=c++11
  • extra_link_args 就是传给 gcc 的额外的链接参数(也就是生成动态链接库的时候用的)

执行下面命令就可以把 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。

2. Windows

其实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 解释器载入会载入这个文件从而找到我们的函数实现。

3. 写出高效的cython

Cython 中类型声明非常重要,但是我们不加类型标注它依然是一个合法的 Cython 程序(这样的又变成Python动态类型的问题,很多编译期间就能确定下来的事情被推到了运行时,性能会打折扣), Cython 提供了一个很好的工具,可以方便地检查 Cython 程序中哪里可能可以进一步优化。下面命令既可以对 XX.pyx 进行分析:
cython -a cython_evaluate.pyx

如果当前 Cython 程序用到了 C++,则需要加上 –cplus 参数。在成功运行完 cython -a 之后,会产生同名的 .html 文件,如下图:
html

网页最上面与说明,黄色部分标识了和 Python 发生交互的地方,点击每一行可以查看相应的生成的 C/C++ 代码。本Bolg相关代码见:github

参考

  1. https://github.com/cython
  2. https://github.com/cython/cython/wiki/Installing
  3. http://docs.cython.org/en/latest/src/quickstart/build.html
  4. https://zhuanlan.zhihu.com/p/24311879?utm_medium=social&utm_source=wechat_session&from=singlemessage&isappinstalled=1
  5. https://stackoverflow.com/questions/125367/dynamic-type-languages-versus-static-type-languages
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值