我需要编写一个脚本,对于4个类似500x500图像的堆栈,逐像素地进行最小二乘拟合。同样,我需要将所有四个图像上特定像素位置的值拟合为长度为3的矢量,对每个像素使用相同的4x3矩阵。
如果没有对每个像素进行嵌套的for循环迭代,我没有看到这样做的方法,所以我认为cython可以加快速度。我之前从未使用过cython,但是我根据文档示例编写了以下代码。
问题是,这比纯python实现(~25秒)运行缓慢或慢(~27秒)。
有谁看到什么减慢了这个?谢谢!
import numpy as np
cimport numpy as np
cimport cython
npint = np.int16
npfloat = np.float64
ctypedef np.int16_t npint_t
ctypedef np.float64_t npfloat_t
@cython.boundscheck(False)
@cython.wraparound(False)
def fourbythree(np.ndarray[npfloat_t, ndim=2] U_mat, np.ndarray[npint_t, ndim=3] G):
assert U_mat.dtype == npfloat and G.dtype == npint
cdef unsigned int z = G.shape[0]
cdef unsigned int rows = G.shape[1]
cdef unsigned int cols = G.shape[2]
cdef np.ndarray[npfloat_t, ndim= 3] a = np.empty((z - 1, rows, cols), dtype=npfloat)
cdef npfloat_t resid
cdef unsigned int rank
cdef Py_ssize_t row, col
cdef np.ndarray s
for row in range(rows):
for col in range(cols):
a[:, row, col] = np.linalg.lstsq(U_mat, G[:, row, col])[0]
return a
答案 0 :(得分:0)
您不应该需要迭代 - 您可以通过一次调用enum RoutineName {
case crunches(name: String)
}
来完成所有操作。 lstsq
允许第二个参数为2D,在这种情况下,结果也是2D。您的阵列是3D,但您可以轻松地将其重新整形为2D,然后重新整形输出(并且重塑基本上是免费的 - 它不需要复制数据):
lstsq
这是所有无类型的纯Python代码,因为这不是任何索引,所以我不希望Cython提供帮助。
我从中获得了400倍的加速(虽然其中一些是因为“一个调用”版本似乎并行运行而Cython版本没有)。我认为加速的主要原因是重复调用Python函数的开销(假设它在很小的数组上工作)。