[英]Matlab efficiency: small for-loop
我寫了一些 Matlab 代碼,到目前為止可以工作,但是在使用大矩陣運行時非常慢。 我將代碼的瓶頸確定為 for 循環。
代碼應該做的是查看 H 矩陣的一列 (ic),與至少有一個與 ic 相同的 1 條目的其他列進行比較,並將它們的列添加到 ic 向量中。 這種情況會一直發生,直到 ic 向量不再發生變化。
這是一個小例子:
H = ( 1 0 1; 1 1 0; 0 0 1 ) 和 ic = ( 1 1 0 )^T (H 的第一列)。 然后代碼以 ic 的第一個 1 為例,在其行中比較另一列是否也有 1 作為其第一個條目,找到第三列 ( 1 0 1 )^T 然后將所有這些添加到 ic 向量在找到的列中,在這種情況下是第三個條目,因此 ic = ( 1 1 1 )^T。
起初我使用了兩個 for 循環:
H是一個 (500 x 1000) 稀疏矩陣(但當代碼運行得更快時應該是 (5000 x 10 000))。
ic是 (500 x 1) 向量。
i是代碼開頭的 ic 向量的索引。
代碼1(舊版本):
for c = find(ic).'
for v = find(H(c,:))
if v ~= i
ic = ic | H(:,v);
end
end
end
然后我嘗試改進我的代碼並通過矢量化使其更快:
代碼2(新版本):
for c = find(ic).'
ic( sum(H(:,find(H(c,:))'),2) > 0 ) = 1;
end
第二行代碼2調用了1769302次,占用了97.4%的時間,也就是30.568s。 它被調用了很多次,因為 ic 向量必須在構造 H 矩陣時確定,並且幾乎在 H 矩陣中添加任何 1 之前被調用。 與代碼 1 相比,時間已經有所改善,其中第二行耗時 20.209 秒,第四行耗時 31.950 秒。 我的目標是使用 (5000 x 10 000) H 矩陣運行我的代碼,並且不超過 3 分鍾。
H 矩陣是在代碼運行時構建的。 在添加到矩陣中的幾乎每個 1 之前,都會調用其中包含上述代碼的 function。 然后 ic 向量在 while 循環中更新,直到它不再變化或 ic 向量中不再有零。 while 循環如下所示:
代碼 3(上下文):
ic2 = ic;
while true
for c = find(ic).'
ic( sum(H(:,find(H(c,:))'),2) > 0 ) = 1;
end
if isequal(ic0,ic)
return;
end
ic0 = ic;
if sum(ic(:,1)) == size(H,1)
return;
else
ic2 = ic;
end
end
ic0的唯一目的是比較迭代之間的ic 。
ic2保存了ic的 state 之前它只包含一個。
我非常感謝任何可以幫助我進一步改善代碼運行時間的答案,我很抱歉在 Matlab 編程方面經驗不足。 非常感謝您的任何回答!
我想這取決於你是否想在添加一個之后再次檢查整個 ic 向量。 因為如果您在向量中的某個點添加一個,您已經處理過,您可能會與其他列有一些新的連接。 但是,如果您不想再次檢查,在將一個添加到 ic 矢量后,您可以使用以下內容:
H = [ 1 0 1 ;
1 1 0 ;
0 0 1 ];
ic = [1;
1;
0];
Htemp = H+ic;
ic = any(H(:, any(Htemp>1)),2);
要檢查直到 ic 不再改變,您可以嘗試以下操作:
ic = H(:,1);
a = true;
s = 0;
ic2 = ic;
while a
Htemp = H+ic;
ic = any(H(:, any(Htemp>1)),2);
Htemp = H+ic;
if s == sum(ic)
a = false;
else
s = sum(ic);
a = true;
end
if sum(ic(:,1)) == size(H,1)
return;
else
ic2 = ic;
end
end
對於我的隨機矩陣,這不會通過 while 循環進行兩次以上的迭代,但它應該完全按照您上面的代碼所做的,只是更快。 計算大約需要 0.9 秒。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.