调整#1
NumPy中经常忽略的一项非常简单的性能调整是避免使用除法和使用乘法。当处理相同形状的数组时,当处理标量到标量或数组到数组的分割时,这并不明显。但是NumPy的隐式广播使其对于允许在不同形状的数组之间或数组与标量之间进行广播的划分变得有趣。对于那些情况,我们可以通过与倒数相乘得到明显的提升。因此,对于所述问题,我们将预先计算的倒数,
a_map并将其用于乘法而不是除法。
因此,一开始要做:
r_a_map = 1.0/a_map
然后,在嵌套循环中,将其用作:
KK_l_obs[I0_ : I0_ + nl, I0_ : I0_ + nl] * r_a_map[si[0], si[1]]
调整#2
我们可以
associative在那里使用乘法的属性:
A*(B + C) = A*B + A*C
因此,
k_l_th可以在所有迭代中求和,但可以在循环外将其保持不变,并在退出嵌套循环后求和。它的有效的总结是:
E.dot(k_l_th).dot(E.T)。因此,我们将其添加到中
K_PC。
定稿和基准测试
使用tweak#1和tweak#2,我们最终会得到一种改进的方法,就像这样-
def original_mod_app(): r_a_map = 1.0/a_map K_PC = np.empty((q, q, X, Y)) inds = np.ndindex((X, Y)) for si in inds: I0_ = I0[si[0], si[1]] K_PC[..., si[0], si[1]] = E.dot( KK_l_obs[I0_ : I0_ + nl, I0_ : I0_ + nl] * r_a_map[si[0], si[1]]).dot(E.T) return K_PC + E.dot(k_l_th).dot(E.T)[:,:,None,None]
使用与问题中使用的样本设置相同的样本进行运行时测试-
In [458]: %timeit original_app()1 loops, best of 3: 1.4 s per loopIn [459]: %timeit original_mod_app()1 loops, best of 3: 677 ms per loopIn [460]: np.allclose(original_app(), original_mod_app())Out[460]: True
因此,我们在那里得到了加速 2x+
。



