14

私は cffi モジュールを python で書いて遊んでいますが、その速度は、標準の python を正しく使用しているかどうか疑問に思っています。完全にCに切り替えたくなる!正直なところ、C で自分自身を再実装することはできなかった素晴らしい Python ライブラリがいくつかあるので、これは実際には何よりも仮説にすぎません。

この例は、numpy 配列で使用されている Python の sum 関数と、ac 関数と比較してどれだけ遅いかを示しています。numpy 配列の合計を計算するより高速な pythonic の方法はありますか?

def cast_matrix(matrix, ffi):
    ap = ffi.new("double* [%d]" % (matrix.shape[0]))
    ptr = ffi.cast("double *", matrix.ctypes.data)
    for i in range(matrix.shape[0]):
        ap[i] = ptr + i*matrix.shape[1]                                                                
    return ap 

ffi = FFI()
ffi.cdef("""
double sum(double**, int, int);
""")
C = ffi.verify("""
double sum(double** matrix,int x, int y){
    int i, j; 
    double sum = 0.0;
    for (i=0; i<x; i++){
        for (j=0; j<y; j++){
            sum = sum + matrix[i][j];
        }
    }
    return(sum);
}
""")
m = np.ones(shape=(10,10))
print 'numpy says', m.sum()

m_p = cast_matrix(m, ffi)

sm = C.sum(m_p, m.shape[0], m.shape[1])
print 'cffi says', sm

関数が機能することを示すためだけに:

numpy says 100.0
cffi says 100.0

この単純な関数の時間を計ると、numpy が本当に遅いことがわかります。numpy を正しい方法で使用していますか? Pythonで合計を計算するより速い方法はありますか?

import time
n = 1000000

t0 = time.time()
for i in range(n): C.sum(m_p, m.shape[0], m.shape[1])
t1 = time.time()

print 'cffi', t1-t0

t0 = time.time()
for i in range(n): m.sum()
t1 = time.time()

print 'numpy', t1-t0

回:

cffi 0.818415880203
numpy 5.61657714844
4

1 に答える 1

14

Numpy が C よりも遅い理由は 2 つあります。Python のオーバーヘッド (おそらく cffi に似ています) と一般性です。Numpy は、さまざまなデータ型の束で、任意の次元の配列を処理するように設計されています。cffi を使用した例は、フ​​ロートの 2D 配列用に作成されました。.sum()コストは、5 マイクロ秒未満を節約するために 6 文字に対して数行のコードを記述することでした。(しかし、もちろん、あなたはすでにこれを知っていました)。CPU 時間は安価であり、開発者の時間よりもはるかに安価であることを強調したいだけです。

Numpy に固執し、パフォーマンスを向上させたい場合は、Bottleneckを使用することをお勧めします。それらは、float と double の 1 および 2D 配列用に最適化されたいくつかの関数を提供し、非常に高速です。あなたの場合、16 倍速くなり、実行時間が 0.35 になり、cffi の約 2 倍になります。

ボトルネックにはないその他の機能については、Cython を使用できます。よりPythonicな構文でCコードを書くのに役立ちます。または、必要に応じて、速度に満足できるまで、Python を C に徐々に変換します。

于 2014-04-14T11:15:55.293 に答える