返回语句时速度慢

时间:2013-02-08 15:01:48

标签: python performance return cython

我有这个cython代码只是为了测试:

cimport cython

cpdef loop(int k):
    return real_loop(k)

@cython.cdivision
cdef real_loop(int k):
    cdef int i
    cdef float a
    for i in xrange(k):
        a = i
        a = a**2 / (a + 1)
    return a

我用这样的脚本测试这个cython代码和纯python中的相同代码之间的速度差异:

import mymodule

print(mymodule.loop(100000))

我快80倍。但是如果我在cython代码中删除两个return语句,我会快8到900倍。为什么?

另一件事是,如果我在旧的ACER Aspire ONE笔记本电脑上运行此代码(带有返回),我可以在家中使用新的桌面i7 PC,速度提高700倍。

有人知道为什么吗?

1 个答案:

答案 0 :(得分:0)

我使用以下代码测试了您的问题:

#cython: wraparound=False
#cython: boundscheck=False
#cython: cdivision=True
#cython: nonecheck=False
#cython: profile=False

def loop(int k):
 return real_loop(k)

def loop2(int k):
 cdef float a
 real_loop2(k, &a)
 return a

def loop3(int k):
    real_loop3(k)
    return None

def loop4(int k):
    return real_loop4(k)

def loop5(int k):
 cdef float a
 real_loop5(k, &a)
 return a

cdef float real_loop(int k):
    cdef int i
    cdef float a
    a = 0.
    for i in range(k):
        a += a**2 / (a + 1)
    return a

cdef void real_loop2(int k, float *a):
    cdef int i
    a[0] = 0.
    for i in range(k):
        a[0] += a[0]**2 / (a[0] + 1)

cdef void real_loop3(int k):
    cdef int i
    cdef float a
    a = 0.
    for i in range(k):
        a += a**2 / (a + 1)

cdef float real_loop4(int k):
    cdef int i
    cdef float a
    a = 0.
    for i in range(k):
        a += a*a / (a + 1)
    return a

cdef void real_loop5(int k, float *a):
    cdef int i
    a[0] = 0.
    for i in range(k):
        a[0] += a[0]*a[0] / (a[0] + 1)

real_loop()靠近你的函数,修改了a的公式,因为原来的公式似乎很奇怪。

函数real_loop2()未返回任何值,只是通过引用更新a

函数real_loop3()未返回任何值。

检查C生成的real_loop3()代码可以看到循环在那里,并且代码被调用...但是我得到了与@dmytro相同的结论,更改了{{1}不会明显改变时间......所以必须有一点我在这里失踪。

从下面的时间我们可以说k不是瓶颈,因为returnreal_loop2()没有返回任何值,而且它们的表现与{{1}相同分别和real_loop5()

real_loop()

请注意real_loop4()的{​​2}加速变化In [2]: timeit _stack.loop(100000) 1000 loops, best of 3: 1.71 ms per loop In [3]: timeit _stack.loop2(100000) 1000 loops, best of 3: 1.69 ms per loop In [4]: timeit _stack.loop3(100000) 10000000 loops, best of 3: 78.5 ns per loop In [5]: timeit _stack.loop4(100000) 1000 loops, best of 3: 913 µs per loop In [6]: timeit _stack.loop5(100000) 1000 loops, best of 3: 979 µs per loop ,因为a**2需要循环内的函数调用a*a