由于性能问题,我开始学习Cython。此特定代码试图在运输建模(用于计划)区域中实施一些新算法。
我决定从一个非常简单的函数开始,我将使用很多(数亿次)并且肯定会从性能提升中受益。
我以三种不同的方式实现了这个功能,并为它们测试了相同的参数(为了简单起见),每次1000万次:
主脚本上的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
答案 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/