python高性能编程_python高性能编程之Cython篇 第一章

第一节 cython的潜能

•Cython是一种编程语言,它将Python与C和C ++的静态类型系统相结合。

•Cython是一个将Cython源代码转换为高效的C或C ++源代码的编译器。然后可以将此源代码编译为Python扩展模块或独立可执行文件。

Cython的强大功能来自它结合了Python和C的方式:感觉就像Python一样,同时提供了对C语言的轻松访问.Cython位于高级Python和低级C之间;有人可能会称它为克里奥尔语编程语言。但是Python和类C语言是如此不同 - 为什么要将它们结合起来?正是因为他们的差异是互补的。 Python具有高级,动态,易学和灵活的特点。然而,这些积极因素带来了成本 - 因为Python是动态的并且是解释的,它可能比静态类型编译慢几个数量级。另一方面,C是广泛使用的最古老的静态类型编译语言之一,因此编译器已经有近半个世纪的时间来优化其性能。 C非常低级且非常强大。与Python不同,它没有很多安全措施,并且很难使用。

两种语言都是主流,但鉴于它们的不同,它们通常用于不同的领域。 Cython的美妙之处在于:它结合了Python的表现力和C的强劲的性能,同时写起来仍然感觉像Python。除了极少数例外,Python代码(版本2.x和3.x)已经是有效的Cython代码。 Cython在Python语言中添加了少量关键字,以利用C的类型,允许cython编译器生成有效的C代码。如果您已经了解Python并且对C或C ++有基本的了解,那么您将能够快速学习Cython。您不必学习另一种新的语言。我们可以将Cython视为一个介于python和c或c++中间的项目。如果将Python编译为C语言是Cython的反面,那么将C或C ++与Python接口就是它的正面。我们可以从需要更好性能的Python代码开始,或者我们可以从需要优化Python接口的C(或C ++)代码开始。为了加速Python代码,Cython使用可选的静态类型声明编译Python源代码,以根据算法实现大规模的性能改进。要使用Python连接C或C ++库,我们可以使用Cython与外部代码进行交互并创建优化的包装器。这两种功能 - 编译Python和与外部代码接口 - 都可以很好地协同工作,每个功能都是Cython有用的重要组成部分。

(补充:

Cython和CPython的区别

Cython经常与CPython混淆(请注意P),但两者是非常不同的。

CPython是标准和最广泛使用的Python实现的名称。

CPython的核心是用C语言编写的,CPython中的C用于区别于Python语言规范和其他语言的Python实现,例如Jython(Java),IronPython(.NET)和PyPy(Python中实现的))。 CPython为Python语言提供了一个C级接口;该接口称为Python / C API。 Cython广泛使用这个C接口,因此Cython依赖于CPython。Cython不是Python的另一个实现 - 它需要CPython运行时来运行它生成的扩展模块。

)

我们来看一个例子吧。

第二节 比较Python,C和Cython

考虑一个简单的Python函数fib,它计算第n个Fibonacci数:1

def fib(n):

a,b=0.0,1.0

for i in range(n):

a,b=a+b,a

return a

正如在介绍中提到的,这个Python函数已经是一个有效的Cython函数,在Python和Cython中它具有相同的行为。 我们很快就会看到我们可以为fib添加基于Cython的特定语法来提高其性能。

下面是纯C语言的实现:

double cfib(int n){

int i;

double a=0.0,b=1.0,tmp;

for(i=0;i

tmp=a;a=a+b;b=tmp;

}

return a;

}

我们在C版本中使用double并在Python版本中以float进行比较直接并删除与C数据类型的整数溢出相关的任何问题。想象将C版本中的类型与Python版本中的代码混合。结果是一个静态类型的Cython版本:

def fib(int n):

cdef int i

cdef double a=0.0,b=1.0

for i in range(n):

a,b=a+b,a

return a

如前所述,Cython和Python代码非常类似,因此我们未经修改的Python fib函数也是有效的Cython代码。转换动态类型的Python版本 为静态类型的Cython版本,我们使用cdef 的Cython语句来声明静态类型的C变量i,a和b。即使对于之前没有看过Cython代码的读者,也是非常直观好理解的。具体的性能比较见下表:注意,这里分别进行了0和90的斐波那契比较,可以看出fib(90)的计算量下cython,纯c以及c扩展的性能非常接近基本一样

在表1-1中,第二列的测量fib(0)和第三列的运行时间

测量是其它三种方式相对于Python的fib(0)的加速。因为fib的参数控制循环迭代的次数,所以fib(0)不会进入Fibonacci循环,因此它的运行时间是语言运行时和函数调用开销的合理度量。(emmm。。。实际上在工业级项目上这一点非计算型的开销 时间还是可以接受的)

第四和第五列测量fib(90)的运行时和加速,其执行循环90次。调用开销和循环执行运行时都有助于其运行时。第六和第七列测量fib(90)运行时和fib(0)运行时之间的差异以及相对加速。这种差异仅仅是循环运行时的近似值,消除了运行时和调用开销。可以看到纯C,C extension以及cython的表现非常类似。

Table 1-1有四行:

纯Python

第一行(在标题之后)测量纯Python版本的fib的性能,并且如预期的那样,在所有类别中,它具有显着的最差性能。特别是,fib(0)的调用开销在该系统上超过半微秒。 fib(90)中的每个循环迭代需要将近150纳秒; Python留下了很大的改进空间。

纯C.

第二行测量纯C版本的fib的性能。在这个版本中,没有与Python运行时的交互,因此最小化 了调用开销;这也意味着它无法从Python中使用。这个版本提供了一个我们可以合理地期望从简单的序列fib函数中获得最佳性能。与Python相比,fib(0)值表示C函数调用开销最小(2纳秒),并且fib(90)运行时(164纳秒)比此特定系统上的Python快近80倍。

手写C扩展

第三行测量Python 2的手写C扩展模块

扩展模块需要几十行C代码,其中大部分都是调用Python / C API的样板。从Python调用时,扩展模块必须将Python对象转换为C数据,计算C中的Fibonacci数,然后进行转换结果返回Python对象。它的调用开销(fib(0)列)相应地大于纯C版本,后者不必从Python对象转换。因为它是用C语言编写的,所以对于fib(0),它比纯Python快三倍。它还为fib(90)提供了一个很好的30倍加速。(https://blog.csdn.net/fitzzhang/article/details/79212411 找到一篇关于c-extension的介绍, 对于python中的C extension并没有太多研究,大概的理解就是用C来写后端的逻辑然后转化为dll这类文件再用python导入)

大概长这样,之后还要进行编译和扩展,具体的可以参考上面的链接里的介绍

#include

static PyObject *module_func(PyObject *self, PyObject *args) {

/* Do your stuff here. */

Py_RETURN_NONE;

}

static PyMethodDef module_methods[] = {

{ "func", (PyCFunction)module_func, METH_VARARGS, NULL },

{ NULL, NULL, 0, NULL }

};

PyMODINIT_FUNC initModule() {

Py_InitModule3(Module, module_methods, "docstring...");

}

---------------------

作者:fitzzhang

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值