为什么Cython中的代码比Python慢​​?

时间:2012-06-25 17:57:07

标签: python performance cython

由于性能问题,我开始学习Cython。此特定代码试图在运输建模(用于计划)区域中实施一些新算法。

我决定从一个非常简单的函数开始,我将使用很多(数亿次)并且肯定会从性能提升中受益。

我以三种不同的方式实现了这个功能,并为它们测试了相同的参数(为了简单起见),每次1000万次:

  • cython模块中的Cython代码。运行时间:3.35秒
  • Cython模块中的Python代码。运行时间:4.88秒
  • 主脚本上的Python代码。运行时间:2.98秒

    正如您所看到的,cython代码比cython模块中的python代码慢45%,比在主脚本上编写的代码慢64%。怎么可能?我在哪里犯了错误?

cython代码是这样的:

def BPR2(vol, cap, al, be):
    con=al*pow(vol/cap,be)
    return con


def func (float volume, float capacity,float alfa,float beta):
    cdef float congest
    congest=alfa*pow(volume/capacity,beta)
    return congest

测试脚本是这样的:

agora=clock()
for i in range(10000000):
    q=linkdelay.BPR2(10,5,0.15,4)

agora=clock()-agora
print agora

agora=clock()
for i in range(10000000):
    q=linkdelay.func(10,5,0.15,4)

agora=clock()-agora
print agora

agora=clock()
for i in range(10000000):
    q=0.15*pow(10/5,4)

agora=clock()-agora
print agora

我意识到超越功能(力量)等问题变得越来越慢,但我认为它应该是一个问题。

由于在函数空间上查找函数存在开销,如果我为函数传递一个数组并返回一个数组,它会有助于提高性能吗?我可以使用用Cython编写的函数返回数组吗?

供参考,我正在使用: - Windows 7 64位 - Python 2.7.3 64位 - Cython 0.16 64位 - Windows Visual Studio 2008

3 个答案:

答案 0 :(得分:3)

使用以下方式进行测试:

for i in range(10000000):
  func(2.7,2.3,2.4,i)

结果如下:

cdef float func(float v, float c, float a, float b):
  return a * (v/c) ** b
#=> 0.85

cpdef float func(float v, float c, float a, float b):
  return a * (v/c) ** b
#=> 0.84

def func(v,c,a,b):
  return a * pow(v/c,b)
#=> 3.41

cdef float func(float v, float c, float a, float b):
  return a * pow(v/c, b)
#=> 2.35

为了获得最高效率,您需要在C中定义函数并使返回类型为静态。

答案 1 :(得分:1)

这个函数可以这样优化(在python和cython中,删除中间变量更快):

def func(float volume, float capacity, float alfa,f loat beta):
    return alfa * pow(volume / capacity, beta)

答案 2 :(得分:0)

当Cython较慢时,可能是由于类型转换,并且可能因缺少类型注释而加剧。此外,如果您在Cython中使用C数据结构,那么比在Cython中使用Python数据结构更快。

我在CPython 2.x(有和没有Cython,有和没有psyco),CPython 3.x(有和没有Cython),Pypy和Jython之间进行了性能比较。 Pypy是迄今为止最快的,至少对于所测试的微观基准来说: http://stromberg.dnsalias.org/~strombrg/backshift/documentation/performance/