我測試你用下面的代碼問題:
#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()
沒有返回任何值。
檢查real_loop3()
一個生成的代碼C
可以看到,循環是存在的,並且代碼被稱爲...但我有同樣的結論爲@dmytro,改變k
不會顯著改變定時...所以必須有一點我在這裏失蹤。
從時序下面我們可以說,return
不是瓶頸,因爲real_loop2()
和real_loop5()
有不返回任何價值,他們的表現是一樣的分別real_loop()
和real_loop4()
。
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
注意〜2倍加速改變由a*a
a**2
,因爲a**2
需要一個函數調用powf()
內循環。
這很難說 - 我不知道如果編譯器將足夠聰明地看到,'real_loop'不更新任何全局變量,它不會改變任何的參數,因此它可以變成一個沒有-OP。 – mgilson 2013-02-08 15:15:04
您是否嘗試對兩個生成的C文件進行「差異化」以查看差異?無論如何,也許是因爲cython認爲沒有'return'的函數是無用的,並且完全循環。 – Bakuriu 2013-02-08 15:49:27
@Bakuriu是的,這是我的想法。可能根本不做循環。我不知道如何,但昨天當我嘗試不同的方式來編碼時,我得到了一些可笑的表現,比如12000倍的速度。 – 2013-02-08 16:02:53