[英]Optimizing Python loop when each loop reads the result of last loop
應該優化由兩個循環(外部和內部)組成的函數-理想情況下是用Numpy函數替換Python循環。 可以輕松優化內部循環(變量inner_loop
),但是也可以更改外部循環嗎?
問題是inner_loop
讀取向量U
,在每個外部循環中都更改了它的一個元素。 如果我使用匹配的Numpy函數優化外循環,則會丟失“遞歸”元素(更新U[i]
)。
for i in (y for y in xrange(0, n)):
inner_loop = -np.sum(self.Y[i, :] * U) + self.Y[i, i] * U[i] + np.conjugate(self.shares[i] / U[i])
U[i] = U_last[i] + accelerator * (1/self.Y[i,i] * inner_loop - U_last[i])
U
是向量(n個維), U_last
和self.shares
, Y
是self.shares
矩陣U。對於那些想知道的人來說,它是高斯-賽德爾功率流算法的一部分。
因為您是遞歸地構建數組,所以沒有。 您必須找出另一種非遞歸算法,或者排除遞歸部分。
讓我們盡力而為。
for i in (y for y in xrange(0, n)):
等同for i in xrange(n)
。 y
沒有任何用途,因為它沒有作為名稱公開。
使用U
更改值的唯一地方是傳遞給np.sum
,因此我們可以通過進行一些預計算來進行一些簡化。
self.Y[i, i] * U[i]
可以為Ydiag_times_U[i]
,其中Ydiag_times_U = np.diag(Y) * U
np.conjugate(self.shares[i] / U[i])
可以是conjugate_shares_over_U[i]
,其中conjugate_shares_over_U = np.conjugate(self.shares/U)
。 U_last[i] + accelerator * (1/self.Y[i,i] * inner_loop - U_last[i])
可以類似地重新排列並制作為U_last_minus_accelerator_times_U_last[i] + accelerator_over_Ydiag[i] * inner_loop
,其中U_last_minus_accelerator_times_U_last[i] + accelerator_over_Ydiag[i] * inner_loop
是
U_last_minus_accelerator_times_U_last[i] = U_last - accelerator * U_last
accelerator_over_Ydiag = accelerator/np.diag(self.Y)
進行更改:
Ydiag_times_U = np.diag(Y) * U
conjugate_shares_over_U = np.conjugate(self.shares / U)
inner_silliness = Ydiag_times_U + conjugate_shares_over_U
U_last_minus_accelerator_times_U_last[i] = U_last - accelerator * U_last
accelerator_over_Ydiag = accelerator/np.diag(self.Y)
for i in xrange(n):
inner_loop = inner_silliness[i] - np.sum(self.Y[i, :] * U)
U[i] = U_last_minus_accelerator_times_U_last[i] + accelerator_over_Ydiag[i] * inner_loop
這些是較低級別的更改。 除此之外,您可以嘗試做一些代數運算以消除遞歸性。 如果您擔心效率,請嘗試使用C進行循環。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.