大きな2Dのnumpy値配列のp値を計算したいと思います。しかし、これには時間がかかり、スピードを上げたいと思います。 GSLを使ってみました。 単一のgsl_cdf_tdist_Pはscipy.stats.t.sfよりはるかに高速ですが、ndarrayを反復処理すると処理が非常に遅くなります。私はこれを改善するために援助をしたいと思います。 下記のコードを参照してください。scipy.stats.t.sfとCythonを使用したGSLの比較
import GSL_Test
import numpy
import scipy.stats
a = numpy.random.rand(3544, 3544).astype('float32')
%timeit -n 1 GSL_Test.get_gsl_p_for_2D_matrix(a, 25)
1 loop, best of 3: 7.87 s per loop
%timeit -n 1 scipy.stats.t.sf(a, 25)*2
1 loop, best of 3: 4.66 s per loop
ipython
GSL_Test.pyx
import cython
cimport cython
import numpy
cimport numpy
from cython_gsl cimport *
DTYPE = numpy.float32
ctypedef numpy.float32_t DTYPE_t
cdef get_gsl_p(double t, double nu):
return (1 - gsl_cdf_tdist_P(t, nu)) * 2
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
cdef get_gsl_p_for_2D_matrix(numpy.ndarray[DTYPE_t, ndim=2] t_matrix, int n):
cdef unsigned int rows = t_matrix.shape[0]
cdef numpy.ndarray[DTYPE_t, ndim=2] out = numpy.zeros((rows, rows), dtype='float32')
cdef unsigned int row, col
for row in range(rows):
for col in range(rows):
out[row, col] = get_gsl_p(t_matrix[row, col], n-2)
return out
def get_gsl_p_for_2D_matrix_def(numpy.ndarray[DTYPE_t, ndim=2] t_matrix, int n):
return get_gsl_p_for_2D_matrix(t_matrix, n)
UPDATE:が、私はまだscipyのダウンロードよりも低い計算時間を短縮することができましたではなく、CDEF宣言を追加します。私はcdef宣言を持つようにコードを修正しました。
%timeit -n 1 GSL_Test.get_gsl_p_for_2D_matrix_def(a, 25)
1 loop, best of 3: 6.73 s per loop
'stats.t.sf'について、あなたは何を知っていますか?なぜあなたは 'cython'のバージョンが速くなると思いますか?私は 'c'に変換できる反復のようなものを探します。 – hpaulj
scipy.stats.t.sfなどのメソッドには、主に入力チェック用のPythonオーバーヘッドがあります。スピードが必要な場合は、FortranまたはCのいずれかで書かれたscipy.special関数を直接使用することができます。より効率的なアルゴリズムや取引されるアルゴリズムがない限り、scipy.specialを少しでも上回る可能性はありますオフスピードで正確さを保ちます。 – user333700
get_gsl_p_for_2D_matrixに別々の 'def'と' cdef'関数を持たせることは利点がありません。 get_gsl_pの戻り値の型を指定することが少し難しくなるかもしれません。 – DavidW