【发布时间】:2016-10-05 22:26:32
【问题描述】:
我想计算一个大型 2D numpy t 值数组的 p 值。但是,这需要很长时间,我想提高它的速度。我尝试使用 GSL。 尽管单个 gsl_cdf_tdist_P 比 scipy.stats.t.sf 快得多,但在遍历 ndarray 时,该过程非常缓慢。我想帮助改善这一点。 请参阅下面的代码。
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)
ipython
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
更新:添加 cdef 声明我能够减少计算时间,但仍不低于 scipy。我修改了代码以具有 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的迭代之类的东西。 -
scipy.stats.t.sf 和其他方法有一些 python 开销,主要用于输入检查。如果你想要速度,那么你可以直接使用用 Fortran 或 C 编写的 scipy.special 函数。我怀疑有可能以任何可观的数量击败 scipy.special 除非有更有效的算法或交易算法关闭速度以确保准确性。
-
为 get_gsl_p_for_2D_matrix 使用单独的
def和cdef函数没有任何好处。为 get_gsl_p 指定返回类型可能会有所帮助。
标签: python numpy scipy cython gsl