3

私はテストのためだけにこの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コードの2つのreturnステートメントを削除すると、800〜900倍速くなります。なんで ?

もう1つのことは、このコードを(returnを使用して)古いACER Aspire ONEノートブックで実行すると、700倍速くなり、自宅の新しいデスクトップi7PCでは80倍速くなります。

誰かが理由を知っていますか?

4

1 に答える 1

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と同じ結論でした。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*aa**2powf()

于 2014-05-27T08:40:02.703 に答える