次のコードで問題をテストしました。
#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と同じ結論でした。k
変更してもタイミングが大幅に変わることはありません...私はここに行方不明です。
以下のタイミングから、とhave は値を返さず、パフォーマンスはそれぞれと と同じで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
ループ内で関数呼び出しが必要なため、~2X のスピードアップが によって変化することに注意しa**2
てください。a*a
a**2
powf()