IT狗工作室

第5篇:Cython中的循环结构优化

2020-04-18  本文已影响0人  铁甲万能狗

Python的for和while循环是灵活和高级的;它们的语法是自然的,读起来像伪代码。Cython支持for和while循环,无需修改。由于循环在本质上通常占据程序运行时的大部分时间,因此需要记住一些指针,以确保Cython可以将Python循环结构转换为高效的C类似结构。

Cython也会自动将循环索引变量i键入为int, 前提是我们不在循环体中的表达式中使用索引。如果我们确实在表达式中使用i,则Cython无法自动推断该操作是否会溢出,并且保守地拒绝推断C整数类型

下面的示例其实和一个原生Python版本的for循环等效的,传入的变量N和索引i都是动态类型

%%cython

cpdef long long calc():
    N=10000000
    cdef long long res=0
    for i in range(N):res+=i
    return res

运行的时间消耗

我们从Cython编译的代码可以知道,原生版本的Python版本的for循环,在Cython编译后的C级别代码,如下图。
也就是在每经历一个循环内部都经历了如下Python内部C级别下的函数检查 PyList_CheckExactPyList-GET_ITEM (或 PySequence_ITEM)并获取range(N)中当前的索引i,遍历的规模达到一个较大的数量级,效率自然慢

高效的做法是

%%cython -a

cpdef long long calc2():
    
    cdef long N=10000000
    cdef long i
    
    cdef long long res
    for i in range(N):res+=i

    return res

运行的时间消耗


由于在执行循环前,对相关的循环变量做静态类型绑定运行的速度提升到原来的13倍,相应地Cython编译器生成的C代码也非常简洁

但如果上面的示例的for in 循环内部涉及到容器(列表,元组,字典等)的循环时,根据情况,类型静态化循环索引变量可能会导致更多开销。若要高效地循环容器,可以考虑使用如下建议

这些方案可能会减少循环开销。我们将在后续了解到更多关于优化循环体的知识

上一篇下一篇

猜你喜欢

热点阅读