16

由于性能问题,我开始学习 Cython。此特定代码是尝试在交通建模(用于规划)领域实现一些新算法。

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

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

  • cython 模块中的 Cython 代码。运行时间:3.35s

  • Cython 模块中的 Python 代码。运行时间:4.88s

  • 主脚本上的 Python 代码。运行时间:2.98s

    如您所见,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 编写的函数返回一个数组吗?

作为参考,我正在使用:

  • 视窗 7 64 位
  • Python 2.7.3 64 位
  • Cython 0.16 64 位
  • 视窗视觉工作室 2008
4

3 回答 3

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 中定义函数并使返回类型为静态。

于 2012-06-25T19:14:11.477 回答
1

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

def func(float volume, float capacity, float alfa,f loat beta):
    return alfa * pow(volume / capacity, beta)
于 2012-06-25T18:11:29.293 回答
1

当 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/

于 2012-06-25T19:14:19.163 回答