我想测试cython
与标准python的性能。这里我有3个函数的例子,它循环200个整数,将相同的数字反复加到结果中,然后返回结果。在timeit
模块中,我让它被调用1.000.000
次。在
第一个例子是:
[frynio@manjaro ctest]$ cat nocdefexample.pyx
def nocdef(int num):
cdef int result = 0
for i in range(num):
result += num
return result
def xd(int num):
return nocdef(num)
下面是第二个(仔细看,第一个函数定义很重要):
^{pr2}$还有第三个,放在主文件里:
[frynio@manjaro ctest]$ cat test.py
from nocdefexample import xd
from cdefexample import xd1
import timeit
def standardpython(num):
result = 0
for i in range(num):
result += num
return result
def xd2(num):
return standardpython(num)
print(timeit.timeit('xd(200)', setup='from nocdefexample import xd', number=1000000))
print(timeit.timeit('xd1(200)', setup='from cdefexample import xd1', number=1000000))
print(timeit.timeit('xd2(200)', setup='from __main__ import xd2', number=1000000))
我用cythonize -a -i nocdefexample.pyx cdefexample.pyx
编译了它,得到了两个.so
s。然后当我运行python test.py
时,会显示:
[frynio@manjaro ctest]$ python test.py
0.10323301900007209
0.06339033499989455
11.448068103000423
所以第一个是def <name>(int num)
。第二个(似乎比第一个快1.5x
)是cdef int <name>(int num)
。最后一个是def <name>(num)
。在
最后一场的表演很糟糕,但那正是我想看的。我感兴趣的是为什么前两个例子不同(我检查了很多次,第二个总是比第一个快~1.5x
)。在
只是因为我指定了返回类型吗?在
如果是这样的话,这是否意味着它们都是cython
函数,还是第一种混合类型的函数?在
首先,您必须知道,在cython函数的情况下,您只测量了调用
cdef
-与def
-函数的开销:C编译器认识到,循环将导致}同样快。在
num*num
,并且直接计算这个乘法而不运行循环-并且乘法对于10**3
和{这可能会让python程序员感到意外,因为python解释器没有进行优化,因此此循环有
^{pr2}$O(n)
-运行时间:现在,调用
cdef
函数要快得多!只需看看生成的用于调用cdef
版本的C代码(实际上python integer的创建已经包含在内):__pyx_f_4test_cdefex
-只是对C函数的调用。与通过整个python机制执行的def
-version调用(这里有点缩写):Cython必须:
num
创建一个python整数,以便能够调用python函数(__Pyx_PyInt_From_int
)__Pyx_GetModuleGlobalName
+PyMethod_GET_SELF
)定位该方法第一次调用可能至少快100倍,但总体速度低于2,这是因为调用“inner”函数并不是唯一需要完成的工作:}必须调用+必须创建结果python整数。在
def
-函数xd
和{有趣的事实:
原因是integer pool表示值
-5
…256
=16^2
,因此可以更快地构造此范围内的值。在在您的示例中,指定返回类型并没有起到那么大的作用:它只决定到python integer的转换在哪里发生——要么在}中发生,但最终会发生。在
nocdef
或{相关问题 更多 >
编程相关推荐