這是我的代碼:
variables=1000;
t=20;
x=zeros(t,t,3);
y=rand(variables,3);
z=rand(t,t,variables);
e=rand(variables,1);
for c=1:variables
x(:,:,1)=x(:,:,1) y(c,1).*((z(:,:,c)-e(c)).^2);
x(:,:,2)=x(:,:,2) y(c,2).*((z(:,:,c)-e(c)).^2);
x(:,:,3)=x(:,:,3) y(c,3).*((z(:,:,c)-e(c)).^2);
end
我怎樣才能提高這個回圈的計算速度?我認為問題是for帶有大c.
uj5u.com熱心網友回復:
MATLAB 中的回圈很慢,這是一個神話,可惜是一個頑固的神話。當您撰寫for回圈時,它會按順序遍歷變數的最后一個維度。這幾乎直接轉化為 FORTRAN 回圈,幾乎沒有使用矢量化進行改進的余地。下面的代碼盡可能地對你的輸出進行矢量化,但并沒有提高性能,盡管reshape()幾乎是免費的,并且嚴重降低了可讀性。
在每次迭代中,您所做的只是計算y(c,1).*((z(:,:,c)-e(c)).^2),并將其添加到總數中。如果我們能夠對該運算式進行矢量化,我們就可以對 的維度求和c以擺脫回圈。
z(:,:,c)-e(c)可以通過將兩個單一維度添加到e:來矢量化reshape(e, [1 1 numel(e)]),然后像往常一樣減去 2 的冪。
乘法 y(c,1)也有效,如果我們將兩個單一維度添加到y(:,1):, reshape(y(:,1), [1 1 numel(e)]),然后像往常一樣再次相乘。
最后,我們只需要對第 3 個維度求和,最終得到我們的t 逐個 t結果:sum(tmp2, 3)。
剩下的就是 中的硬編碼三個維度x,我將其置于回圈中。
R2007b 上的作業代碼:
variables=10;
t=2;
x=zeros(t,t,3);
y=rand(variables,3);
z=rand(t,t,variables);
e=rand(variables,1);
for ii = 1:size(x, 3)
x(:, :, ii) = sum(bsxfun(@times, reshape(y(:,1), [1 1 numel(e)]), bsxfun(@minus, z, reshape(e, [1 1 numel(e)])).^2), 3);
end
我不確定如何處理 的硬編碼維度3,所以我只是在上面留下了一個回圈。其余部分被矢量化掉了,這要歸功于reshape()為擴展安排維度的幾次呼叫bsxfun()。
>R2016b 的隱式擴展代碼:
for ii = 1:size(x, 3)
x(:, :, ii) = sum(reshape(y(:,ii), [1 1 numel(e)]) .* (z - reshape(e, [1 1 numel(e)])).^2, 3)
end
快速計時比較表明這比原始回圈快大約 2 倍:
Elapsed time is 0.780516 seconds. Original code
Elapsed time is 0.397369 seconds. My bsxfun() solution
Elapsed time is 0.305160 seconds. My implicit expansion
請注意,在上面,每個代碼版本運行了 100 個回圈,即每個版本的時間分別為 8 毫秒、4 毫秒和 3 毫秒。
關于你的介紹reshape()可以參考我的這個回答。
關于隱式廣播的檔案文章相當不錯,這個博客也是如此。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/536588.html
標籤:软件for循环优化
上一篇:消失的主帖在哪里?
下一篇:如何在for回圈中賦值?
