なぜCFFIがNumpyよりもはるかに速いのですか?
-
23-12-2019 - |
質問
私はPythonでCFFIモジュールを書いて遊んでいます、そして彼らのスピードは私が標準的なPythonを正しく使っているのであれば私に不思議にしています。それは私が完全にCに切り替えたいと思っています!真実にいくつかの素晴らしいPythonライブラリがあります
この例は、Numpy配列で使用されているPythonのSUM関数、およびC関数と比較して遅くなるかを示しています。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を使っていますか?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
. 解決
numpyは2つの理由でcより遅くなります.Pythonのオーバーヘッド(おそらくCFFIと同様)と一般性。 Numpyは、任意の寸法の配列、さまざまなデータ型で対応するように設計されています。 CFFIを持つあなたの例は、2Dのフロートアレイに対して行われました。コストは、5マイクロ秒未満のコードVS .sum()
、6文字の数行を書き込んでいました。 (もちろん、あなたはすでにこれを知っていました)。私はCPU時間が安く、開発者の時間よりもはるかに安価であることを強調したいだけです。
今すぐあなたがしゃじに固執したい場合は、より良いパフォーマンスを得たい場合は、ボトルネック。それらは、1および2Dのフロートアレイに対して最適化されたいくつかの関数を提供し、それらは急速に燃えています。あなたの場合、16倍高速で、これは0.35で実行時間をかけるか、CFFIの約2倍の速さです。
ボトルネックがない他の機能では、Cythonを使用できます。それはあなたがよりPythonic構文でCコードを書くのを助けます。あるいは、あなたがそうであれば、あなたが速度に満足するまでPythonをcに進みます。