【发布时间】:2014-10-06 10:08:17
【问题描述】:
我正在使用 numpy 1.9、python 2.7 和 opencv,处理大矩阵,我必须多次执行以下操作
def sumShifted(A): # A: numpy array 1000*1000*10
return A[:, 0:-1] + A[:, 1:]
如果可能的话,我想优化这个操作;我尝试使用Cython,但没有得到任何显着改善,但我不排除这是因为我的实施不当。
有没有办法让它更快?
编辑:
sumShifted 在这样的 for 循环中被调用:
for i in xrange(0, 400):
# ... Various operations on B
A = sumShifted(B)
# ... Other operations on B
#More detailed
for i in xrange(0, 400):
A = sumShifted(a11)
B = sumShifted(a12)
C = sumShifted(b12)
D = sumShifted(b22)
v = -upQ12/upQ11
W, X, Z = self.function1( input_matrix, v, A, C[:,:,4], D[:,:,4] )
S, D, F = self.function2( input_matrix, v, A, C[:,:,5], D[:,:,5] )
AA = self.function3( input_matrix, v, A, C[:,:,6], D[:,:,6] )
BB = self.function4( input_matrix, v, A, C[:,:,7], D[:,:,7] )
EDIT2:按照您的建议,我创建了这两个可运行的基准测试(使用 Cython),将 4 个 sumShifted 方法合并为一个。
A, B, C, D= improvedSumShifted(E, F, G, H)
#E,F: 1000x1000 matrices
#G,H: 1000x1000x8 matrices
#first implementation
def improvedSumShifted(np.ndarray[dtype_t, ndim=2] a, np.ndarray[dtype_t, ndim=2] b, np.ndarray[dtype_t, ndim=3] c, np.ndarray[dtype_t, ndim=3] d):
cdef unsigned int i,j,k;
cdef unsigned int w = a.shape[0], h = a.shape[1]-1, z = c.shape[2]
cdef np.ndarray[dtype_t, ndim=2] aa = np.empty((w, h))
cdef np.ndarray[dtype_t, ndim=2] bb = np.empty((w, h))
cdef np.ndarray[dtype_t, ndim=3] cc = np.empty((w, h, z))
cdef np.ndarray[dtype_t, ndim=3] dd = np.empty((w, h, z))
with cython.boundscheck(False), cython.wraparound(False), cython.overflowcheck(False), cython.nonecheck(False):
for i in range(w):
for j in range(h):
aa[i,j] = a[i,j] + a[i,j+1]
bb[i,j] = b[i,j] + b[i,j+1]
for k in range(z):
cc[i,j,k] = c[i,j,k] + c[i,j+1,k]
dd[i,j,k] = d[i,j,k] + d[i,j+1,k]
return aa, bb, cc, dd
#second implementation
def improvedSumShifted(np.ndarray[dtype_t, ndim=2] a, np.ndarray[dtype_t, ndim=2] b, np.ndarray[dtype_t, ndim=3] c, np.ndarray[dtype_t, ndim=3] d):
cdef unsigned int i,j,k;
cdef unsigned int w = a.shape[0], h = a.shape[1]-1, z = c.shape[2]
cdef np.ndarray[dtype_t, ndim=2] aa = np.copy(a[:, 0:h])
cdef np.ndarray[dtype_t, ndim=2] bb = np.copy(b[:, 0:h])
cdef np.ndarray[dtype_t, ndim=3] cc = np.copy(c[:, 0:h])
cdef np.ndarray[dtype_t, ndim=3] dd = np.copy(d[:, 0:h])
with cython.boundscheck(False), cython.wraparound(False), cython.overflowcheck(False), cython.nonecheck(False):
for i in range(w):
for j in range(h):
aa[i,j] += a[i,j+1]
bb[i,j] += b[i,j+1]
for k in range(z):
cc[i,j,k] += c[i,j+1,k]
dd[i,j,k] += d[i,j+1,k]
return aa, bb, cc, dd
【问题讨论】:
-
你能给我们看一些代码来解释
sumShifted是如何被调用的吗? -
@Rowandish [1000,1000,10] 矩阵并不大,但是,您能否也发布您的
.timeit()测量结果,了解您的初始实施速度是多少,以便对任何事物进行基准测试好还是不好? -
@unutbu 编辑了问题
-
我认为没有办法显着改善
A[:, 0:-1] + A[:, 1:]。改进for-loop可能是可能的。您能否发布一个我们可以进行基准测试和讨论的最小工作示例? -
@Rowandish:恐怕有误会。与其尝试优化
sumShifted,不如尝试优化for-loop。如果您需要帮助,我们需要更详细地了解整个for-loop中发生了什么。可能有办法改进它,也可能没有。但是除非我们能看到完整的代码,否则这是不可能的。如果您知道这不是瓶颈,您可以用虚拟代理函数替换function1到function4。但我们需要看到更多,因为就目前而言,您可以通过完全删除for-loop来提高性能。
标签: python performance numpy matrix cython