c语言函数调用的前期绑定,【翻译】Cython教程7_Cython加速之早期绑定机制(early binding) | 勤奋的小青蛙...

作为一种动态语言,Python鼓励使用一种编程风格,根据其方法和属性来考虑类和对象,而不是它们适合于类层次结构。

这可以使Python成为一种非常轻松和舒适的语言,用于快速开发,但是有一个代价 - 管理数据类型的“繁文。节”被转储到翻译器上。在运行时,解释器在搜索命名空间,获取属性和解析参数和关键字元组方面做了大量工作。与“早期绑定”语言(如C ++)相比,这种运行时“后期绑定”是Python相对较慢的主要原因。

然而使用Cython可以通过使用“早期绑定”编程技术获得显着的加速。

例如,考虑以下(愚蠢)代码示例:

cdef class Rectangle:

cdef int x0, y0

cdef int x1, y1

def __init__(self, int x0, int y0, int x1, int y1):

self.x0 = x0; self.y0 = y0; self.x1 = x1; self.y1 = y1

def area(self):

area = (self.x1 - self.x0) * (self.y1 - self.y0)

if area < 0:

area = -area

return area

def rectArea(x0, y0, x1, y1):

rect = Rectangle(x0, y0, x1, y1)

return rect.area()

在rectArea()方法中,对rect.area()和area()方法的调用包含大量的Python开销。

然而,在Cython中,可以在Cython代码中发生调用的情况下消除大量的这种开销。例如:

cdef class Rectangle:

cdef int x0, y0

cdef int x1, y1

def __init__(self, int x0, int y0, int x1, int y1):

self.x0 = x0; self.y0 = y0; self.x1 = x1; self.y1 = y1

cdef int _area(self):

cdef int area

area = (self.x1 - self.x0) * (self.y1 - self.y0)

if area < 0:

area = -area

return area

def area(self):

return self._area()

def rectArea(x0, y0, x1, y1):

cdef Rectangle rect

rect = Rectangle(x0, y0, x1, y1)

return rect._area()

这里,在Rectangle扩展类中,我们定义了两个不同的区域计算方法,即有效的_area()C方法和Python-callable area()方法,它们作为_area()周围的一个薄包装。注意在函数rectArea()中,我们如何通过声明明确给出类型Rectangle的局部变量rect来“早期绑定”。通过使用此声明,而不是仅仅动态分配给rect,我们获得了访问更高效的C-callable _area()方法的能力。

但是,Cython再次为我们提供了更多的简单性,通过允许我们声明双重访问方法 - 可以在C级高效调用的方法,但也可以以纯Python代码访问,代价是Python访问开销。考虑这个代码:

cdef class Rectangle:

cdef int x0, y0

cdef int x1, y1

def __init__(self, int x0, int y0, int x1, int y1):

self.x0 = x0; self.y0 = y0; self.x1 = x1; self.y1 = y1

cpdef int area(self):

cdef int area

area = (self.x1 - self.x0) * (self.y1 - self.y0)

if area < 0:

area = -area

return area

def rectArea(x0, y0, x1, y1):

cdef Rectangle rect

rect = Rectangle(x0, y0, x1, y1)

return rect.area()

注意:在Cython的早期版本中,cpdef关键字是rdef - 但具有相同的效果)。

在这里,我们只有一个单一的区域方法,被声明为cpdef,使其有效地被称为C函数,但仍然可以从纯Python(或后期绑定的Cython)代码访问。

如果在Cython代码中,我们有一个已经“早期绑定”的变量(即,明确声明为Rectangle类型,或者转换为Rectangle类型),那么调用其区域方法将使用高效的C代码路径并跳过Python开销。但是,如果在Pyrex或普通的Python代码中,我们有一个存储Rectangle对象的常规对象变量,那么调用area方法将需要:

区域方法的属性查找

包装一个元组的参数和一个关键字的dict(在这种情况下都是空的)

使用Python API调用的方法

并在区域方法本身内:

解析元组和关键字

执行计算代码

将结果转换为python对象并返回

所以在Cython中,可以通过在声明和转换变量中使用强类型来实现大量的优化。对于使用方法调用的紧密循环,这些方法是纯C语言实现的,相比Python语言,运行速度可是绝对占优势的。

文章的脚注信息由WordPress的wp-posturl插件自动生成

|2|left

打赏

1b6439c6a040252321edad911c85491b.png微信扫一扫,打赏作者吧~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值